Compare commits

...
Author SHA1 Message Date
Stan Shebs 9277192e15 Forestall a filesystem bug while building shlib.lds by using a temp file 2019-08-14 10:20:07 -07:00
Joseph Myers 353f79819c Fix nan functions handling of payload strings (BZ16962, CVE-2014-9761) 2017-01-19 14:01:46 -08:00
Andreas Schwab e1c67173bf Missing unwind info in __startcontext causes infinite loop (BZ20435, CVE-2016-6323) 2017-01-18 12:56:41 -08:00
Paul Pluzhnikov d701c3a0a5 Fix catopen() Multiple unbounded stack allocations (BZ17905, CVE-2015-8779) 2017-01-18 12:28:50 -08:00
Stan Shebs 19d0f70b08 hcreate, hcreate_r should fail with ENOMEM if element count is too large (BZ18240, CVE-2015-8778) 2017-01-18 07:46:22 -08:00
Stan Shebs b95393ecb5 Always enable pointer guard 2017-01-18 07:43:43 -08:00
Stan Shebs 79ab0fcfda Fix where out of range data to strftime() causes a segfault (BZ18985, CVE-2015-8776) 2017-01-12 21:07:13 -08:00
Stan Shebs 882f407875 Make GRTE testing great again, actually run the test programs 2017-01-12 12:54:46 -08:00
Stan Shebs a998069c80 Don't read past end of pattern in fnmatch (BZ17062) 2017-01-10 18:44:57 -08:00
Stan Shebs 85ea40f66d Don't ignore too long lines in nss_files (BZ17079, CVE-2015-5277) Tested: 2016-12-28 13:51:37 -08:00
Stan Shebs b6099fb5b2 Handle a not-found case in borg passwd lookup 2016-11-03 16:31:52 -07:00
Michael Rothwell 929275c193 Call the correct function. 2016-09-30 09:46:48 -07:00
Michael Rothwell ad9d6e1dbe Augment borg-pwd to also search through passwd.borg.base, if it exists. 2016-09-30 06:09:04 -07:00
Stan Shebs 74b27c48cb Revert the fix to the value of DT_PPC64_NUM. 2016-09-29 12:10:48 -07:00
Stan Shebs f01f990def Fix error handling in getaddrinfo. 2016-08-05 14:12:59 -07:00
Stan Shebs c0872d83ef Fix stack overflow in hostent translation (CVE-2016-3706) 2016-07-14 11:12:46 -07:00
Max Kanat-Alexander 30bb510293 Update nss_cache.c and nss_cache.h to current upstream version. This makes getgrgid_r and similar calls over 20x faster on corp machines. 2016-07-06 14:47:51 -07:00
Stan Shebs bdf9cbb2db Backport checking of locale environment handling 2016-06-27 09:36:28 -07:00
Stan Shebs a39e9f7a23 fix where getaddrinfo() writes DNS queries to random file descriptors under high load (BZ15946, CVE-2013-7423) 2016-05-09 13:54:38 -07:00
Stan Shebs a48e32ee70 Fix stack overflow in _nss_dns_getnetbyname_r (BZ19879) 2016-05-09 10:29:27 -07:00
Stan Shebs c93632edca Fix infinite loop on process exit. 2016-04-27 09:53:33 -07:00
Stan Shebs 000f2cf415 Remove uses of operand modifier (%s) in powerpc inline asm. 2016-02-16 13:39:03 -08:00
Stan Shebs 409bde58fe Backport several dozen PPC-specific patches from IBM. 2016-02-12 18:29:41 -08:00
Stan Shebs 74df977401 Small fix to patch from last October, lets tst-key5 build. 2016-02-10 14:55:24 -08:00
Vicent Segui Pascual bab244a006 Use munlock before madvise to make sure that we effectively "uncommit" the page 2016-01-18 02:05:31 -08:00
Brooks Moses fa9a6cbaea For b/25900273, adjust allocations to avoid segfault. 2015-12-15 10:57:38 -08:00
Stan Shebs 587c53b344 Backport removal of __gconv_translit_find 2015-12-03 14:18:23 -08:00
Stan Shebs f495bb0484 Backport fix for broken trig functions 2015-12-01 09:52:57 -08:00
Manuel Klimek 0428bae673 Allow suppressing the definition of __USE_FILE_OFFSET64 by defining SUPPRESS_USE_FILE_OFFSET64 in the CROSSTOOL. 2015-10-29 10:29:55 -07:00
Stan Shebs 2387d2fc7c Backport of fix for memory leak in getaddrinfo() 2015-10-15 09:22:35 -07:00
Andrew Hunter 497c190870 Make pthread_getspecific async-signal-safe 2015-10-13 10:39:00 -07:00
Paul Pluzhnikov 14cfc78089 For b/22641205, #include _itoa.h 2015-10-10 09:26:54 -07:00
Paul Pluzhnikov bbffc56aa5 For b/20141439, don't add "foo.so" as alternate name for previously loaded "foo.so/@0x..." 2015-10-02 07:31:16 -07:00
Stan Shebs 107aed9f2b Backport upstream fix to nss_files 2015-09-16 10:29:39 -07:00
Stan Shebs b1342139cd Backport upstream fixes to fnmatch 2015-08-31 13:22:13 -07:00
Stan Shebs db2523b0da Describe borg-pwd better, remove dead code. 2015-08-21 14:50:53 -07:00
Brooks Moses 5ccef4d197 Add README.google description omitted from cl/100732637. 2015-08-18 18:07:15 -07:00
Stan Shebs 4be23b8484 Backport fix for BZ 18287 (CVE-2015-1781) 2015-08-17 14:39:38 -07:00
Brooks Moses e52611a110 Backport cl/98967227 to GRTE glibc 2.19 sources. 2015-08-14 22:32:51 -07:00
Stan Shebs b2b6bfcde6 Fix b/19824366 with a local patch (as upstream is fixed unmergeably), and add a new test. 2015-07-28 10:17:46 -07:00
Sriraman Tallam 3532d2e2bc Redeclare hot external libc functions with new GCC function attribute "noplt" to allow calls to these functions to avoid the PLT. This change improves 2015-07-27 10:14:19 -07:00
Stan Shebs d1c2791a63 backport fix buffer overflow for writes to memory buffer stream (PR18549) 2015-07-06 20:51:10 -07:00
Andrew Hunter 1153d5eaf4 Prevent wasted memory in guard regions 2015-06-23 12:58:32 -07:00
Paul Pluzhnikov 10d353539f For b/8315591, b/20141439 correct off-by-one error that resulted in last byte of l_name being random garbage. 2015-06-03 08:58:35 -07:00
Nick Lewycky e19fc0ea57 Change this offsetof computation to use c89 offsetof. Tested: 2015-04-16 11:15:58 -07:00
Stan Shebs 2963bd873f Backport fix for wscanf Tested: 2015-03-13 15:29:01 -07:00
Stan Shebs d37331c9ef Backport fix for getnetbyname Tested: 2015-02-05 19:48:08 -08:00
Brooks Moses daee27e94c Port "resolv.conf timestamp checks" fixes from eglibc sources. 2015-01-30 14:01:03 -08:00
Paul Pluzhnikov 1d1e0535b6 For b/18243822, add back code that was accidentally deleted at the last minute in cr/80600560, and which is required to actually make 2014-12-04 13:56:47 -08:00
Sterling Augustine 13e6e91707 Use ENTRY and END macros to get a .size directive. backport of change: 2014-11-25 14:49:54 -08:00
Sterling Augustine cc586e77cf For b/18473397 and CVE-2014-7817, properly handle the WRDE_NOCMD flag when processing certain arithmetic inputs. 2014-11-25 13:49:28 -08:00
Paul Pluzhnikov c4273619e1 Fix arm build by only using _itoa when building ld-linux, and not 'sln'. Also disable __google_dlopen_with_offset in fully-static link 2014-11-23 18:12:56 -08:00
Paul Pluzhnikov 98337c55db For b/18243822, fix dlopen_with_offset to not reuse the same link_map entry when called on the same file with different offsets. 2014-11-10 10:56:25 -08:00
Brooks Moses 69f4e2a55d Export a __secure_getenv symbol for link-time compatibility with GRTEv3. Tested: 2014-09-24 04:21:40 -07:00
Brooks Moses a0db2d6209 Import ldd patch from Ubuntu sources to allow ldd to work with non-executable files. 2014-09-12 10:34:21 -07:00
Brooks Moses 4ddf6cb7a6 For b/15780211, consolidate setting of __google_auxv into earliest possible location. (Forward-port of cl/69729332.) 2014-06-30 16:10:29 -07:00
Paul Pluzhnikov 007f8306a3 For b/13901604 (suid-root exe + unsecure environment variable => wrong __google_auxv), forward-port the second part of the fix (http://cr/69343116) to GRTEv4 via 2014-06-19 19:57:57 -07:00
Brooks Moses 95d48c5aea Forward-port cl/42676407 to disable link-time warning about mktemp, tempnam and tmpnam. 2014-06-12 21:59:51 -07:00
Brooks Moses c88182c608 For b/15017950, backport patches to fix offset computation for append+ mode on switching from read. 2014-06-12 20:55:39 -07:00
Brooks Moses 85a9363da4 Automated g4 rollback of changelist 69114074. 2014-06-12 19:45:48 -07:00
Brooks Moses 5025db781e For b/15017950, backport patch to fix offset computation for append+ mode on switching from read. 2014-06-12 17:30:07 -07:00
Brooks Moses b0da5c6e78 For b/15568332, backport patch to copy path argument to posix_spawn_file_actions_addopen. (Forward-port of cl/69112129) 2014-06-12 17:14:02 -07:00
Paul Pluzhnikov 7241b75ecc For b/13901604, forward-port http://cr/68404571 via 2014-06-02 22:59:19 -07:00
Brooks Moses fa5cf22b84 Backport PPC ELFv2 s_copysign stack temp bugfix (PR16786, b/13737066). 2014-05-19 15:05:10 -07:00
Brooks Moses ed6d472ee9 Backport upstream fixes for PR16532 (separate ftell, fseek logic) for b/15017950. 2014-05-19 14:58:45 -07:00
Brooks Moses ecce267984 For b/14616463, add -fno-function-sections to nptl/events.c compilation. 2014-05-08 15:32:21 -07:00
Brooks Moses e5e5c541b5 Add PTRACE_EVENT_STOP, as per b/13432624. 2014-04-29 18:30:32 -07:00
Brooks Moses 1ecb690ee6 For b/14302447, backport upstream patches for __bzero_ppc. 2014-04-25 13:59:50 -07:00
Brooks Moses ae4d5ce7de For b/12342355, remove inappropriate assert in EXEC_ORIGIN support. 2014-04-11 13:37:15 -07:00
Brooks Moses e2172e072d For b/5732800, expose calls from malloc to mmap,munmap, etc. (Forward-ported from cl/42670015) 2014-03-13 16:21:31 -07:00
Paul Pluzhnikov 17c46147bc For Google b/8315591, experimental implementation of dlopen_with_offset. 2014-03-10 14:02:07 -07:00
Paul Pluzhnikov 05fc85cb17 Add pthread_signal_safe_key_create. 2014-03-08 17:01:11 -08:00
Paul Pluzhnikov b24016d7ef For b/4074041, add EXEC_ORIGIN support. Forward-ported from cl/56955623 and http://cl/59961863. 2014-03-08 15:12:52 -08:00
Paul Pluzhnikov 3a16b5db47 Export __signal_safe* functions from ld.so so we can use a different implementation. 2014-03-08 11:19:25 -08:00
Paul Pluzhnikov 4e6b7daedf For b/13350520, disable check-abi 2014-03-07 10:17:26 -08:00
Paul Pluzhnikov 9fc67c6aa6 Adjust the size value on _nl_default_dirname to match the directory name that we use in GRTE builds so that "make check-abi" will 2014-03-06 14:59:25 -08:00
Paul Pluzhnikov a17c57fab6 Add "fastload" support. 2014-03-04 19:07:05 -08:00
Paul Pluzhnikov c6679b5e43 For b/5013921, build pthread_join.c and pthread_timedjoin.c with frame pointers. 2014-03-03 17:19:26 -08:00
Paul Pluzhnikov ad06b0b3fb For b/5836136, do dlsym(0, "_Unwind..."), i.e. ignore libgcc_s.so.1 dlopen failure. 2014-03-03 17:03:35 -08:00
Paul Pluzhnikov 33838f184a For b/3133396, ignore system ld.so.cache when looking for nss and iconv modules. 2014-03-03 16:18:01 -08:00
Paul Pluzhnikov bd853af031 For b/2471323, implement multi-level cache search for shared libraries. 2014-03-03 15:25:38 -08:00
Paul Pluzhnikov 630cc91e1b For b/3162458, don't skip files with d_ino==0 -- our tmpfs systems sometimes create them due to inode wraparound. 2014-03-03 11:08:11 -08:00
Paul Pluzhnikov f5f58a704c Effectively revert an upstream patch to print signs on NaN values. 2014-03-03 09:18:29 -08:00
Paul Pluzhnikov 63473c3676 Disable gcc's __warn_unused_result__ attribute in glibc headers when _GOOGLE_FORTIFY_SOURCE_NO_WARN_UNUSED_RESULT is specified. 2014-02-28 17:22:06 -08:00
Paul Pluzhnikov 283b5c7b39 For b/4268901, disable "/etc/ld.so.preload". 2014-02-28 17:18:54 -08:00
Paul Pluzhnikov 4e73acc04a For b/2723095, allow grantpt() to succeed even if it can't chgrp the slave pty to the "tty" group. 2014-02-28 17:15:51 -08:00
Paul Pluzhnikov 3fae2a38f8 Reduce starting table sizes for locale-archive file, since we use only a small fraction of the entries. 2014-02-28 17:12:02 -08:00
Paul Pluzhnikov cdaac281f2 Set __MAX_ALLOCA_CUTOFF to 8kb to avoid stack overflow, as described in b/2425017. 2014-02-28 17:08:18 -08:00
Paul Pluzhnikov 2fc36ac70a Add _google_dl_debug_state_hook. This is used by libunwind; see comment in //google3/third_party/grte/google_glibc_extensions.h. 2014-02-28 17:04:05 -08:00
Paul Pluzhnikov 7da5656bd2 Correct comment per cr/62375346 review. 2014-02-28 16:58:53 -08:00
Paul Pluzhnikov ada1223ac9 Add __GOOGLE_GRTE_VERSION__ for GRTEv4 usage. Forward-ported with date and comment changed from cl/51277131. 2014-02-28 16:56:23 -08:00
Paul Pluzhnikov ae1a407796 Disable static linking warning for dlopen and dlmopen, and disable linking warning for sys_errlist and sys_nerr. 2014-02-28 16:51:12 -08:00
Paul Pluzhnikov 8623844f33 Add __google_auxv. Forward-ported from cl/51271693 (from cl/38027-p2). 2014-02-28 16:47:23 -08:00
Paul Pluzhnikov dc8069787a For bit-identical rebuilds, remove date invocations. Forward-ported from cl/51218346. 2014-02-28 15:59:52 -08:00
Paul Pluzhnikov 3ba0025a84 Don't put absolute pathnames into libc.so and libpthread.so linker scripts -- absolute pathnames interfere with --sysroot. 2014-02-28 15:47:22 -08:00
Paul Pluzhnikov 019516567f For b/2476399, disable Hesiod (not used in google) 2014-02-28 15:10:49 -08:00
Paul Pluzhnikov 7839c2120f Disable libnss_db and libnss_nis{,plus} libnss_compat 2014-02-28 14:53:33 -08:00
Paul Pluzhnikov b117857fe2 Integrate nss_{borg,cache} local changes from glibc-2.18 to 2.19 2014-02-28 12:54:06 -08:00
Paul Pluzhnikov 9949268a53 Forward-port google-nsl-stub 2014-02-28 06:44:46 -08:00
Brooks Moses 949ad730d5 Revert upstream removal of async-safe TLS patches. 2014-02-24 11:04:49 -08:00
Paul Pluzhnikov 09ac904b12 Add a skeleton README.google 2014-02-09 00:00:00 -08:00
316 changed files with 11692 additions and 1977 deletions
+7 -6
View File
@@ -458,8 +458,8 @@ $(common-objpfx)shlib.lds: $(common-objpfx)config.make $(..)Makerules
$(LINK.o) -shared -Wl,-O1 \
-nostdlib -nostartfiles \
$(sysdep-LDFLAGS) $(rtld-LDFLAGS) $(LDFLAGS.so) \
-Wl,--verbose 2>&1 | \
sed > $@T \
-Wl,--verbose 2>&1 >$@-tmp
sed $@-tmp > $@T \
-e '/^=========/,/^=========/!d;/^=========/d' \
$(if $(filter yes,$(have-hash-style)), \
-e 's/^.*\.gnu\.hash[ ]*:.*$$/ .note.ABI-tag : { *(.note.ABI-tag) } &/' \
@@ -958,9 +958,9 @@ $(inst_libdir)/libc.so: $(common-objpfx)format.lds \
echo ' Use the shared library, but some functions are only in';\
echo ' the static library, so try that secondarily. */';\
cat $<; \
echo 'GROUP ( $(slibdir)/libc.so$(libc.so-version)' \
'$(libdir)/$(patsubst %,$(libtype.oS),$(libprefix)$(libc-name))'\
' AS_NEEDED (' $(rtlddir)/$(rtld-installed-name) ') )' \
echo 'GROUP ( libc.so$(libc.so-version)' \
'$(patsubst %,$(libtype.oS),$(libprefix)$(libc-name))'\
' AS_NEEDED (' $(rtld-installed-name) ') )' \
) > $@.new
mv -f $@.new $@
@@ -1256,7 +1256,8 @@ endif
ifeq ($(build-shared),yes)
ifdef subdir
tests: check-abi
# Temporarily disable check-abi: http://b/13350520
# tests: check-abi
endif
endif
+703
View File
@@ -0,0 +1,703 @@
Patches applied to glibc-2.19
Please include a change to this file with each patch, *and* each
subsequent modification of the patch. Do NOT combine patch
checkins, keep them separate.
Append new entries to the end of this file. Each entry shall include:
* The list of files modified by the patch,
* The status of the patch. Should be one of:
- already upstream (indicate upstream revision),
- not yet upstream, or
- google-local (not applicable upstream).
* The local 'owner' responsible for the patch, and
* A description of the patch (preferably including bug numbers).
Please include entries for both local patches and for patches which
have been checked in to (or back-ported from) the upstream sources.
When checking in changes made upstream, add an entry to this file but
DO NOT add entries to the GNU ChangeLog files.
elf/Versions
elf/dl-misc.c
elf/dl-open.c
elf/dl-reloc.c
elf/dl-tls.c
nptl/Makefile
nptl/allocatestack.c
nptl/tst-tls7.c
nptl/tst-tls7mod.c
sysdeps/generic/ldsodefs.h
Revert upstream removal of async-safe TLS patches. These patches were
removed at the last minute from the glibc 2.19 release, as follows:
https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=8b6785f0836011cace9a77f3c24e51a7379238a0
https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=dd654bf9ba1848bf9ed250f8ebaa5097c383dcf8
https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=73d61e4f6c65da714c0f8a3a233725322553ceba
https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=bf06bcee84d4c19a99925c0f58026a8cbd87a688
(ahh, not yet upstream)
google-nsl-stub/Makefile
google-nsl-stub/configure
google-nsl-stub/shlib-versions
google-nsl-stub/ypclnt.c
For b/2832143 and b/10385480, add a stub libnsl library as an add-on, to
replace the libnsl removed in the previous change. Although we do not use
libnsl normally, we have precompiled third-party binaries that need to
dynamically link to it, and this stub satisfies that need.
(bmoses, google-local)
Versions.def
shlib-versions
include/grp.h
include/pwd.h
include/shadow.h
nss/Makefile
nss/Versions
nss/function.def
nss/nss_borg/borg-pwd.c
nss/nss_cache/nss_cache.c
nss/nss_cache/nss_cache.h
Forward-port nss_borg and nss_cache from glibc-2.18
(ppluzhnikov, google-local)
nis/Makefile
nss/Makefile
For b/2476399, disable libnss_db (not used in google).
Likewise ibnsl and related libnss_* libraries.
Forward-ported from cl/52538169 and cl/52538711.
(ppluzhnikov, bmoses, google-local)
hesiod/Makefile
For b/2476399, disable Hesiod (not used in google).
Forward-ported from cl/52537558.
(ppluzhnikov, google-local)
Makerules
nptl/Makefile
Don't put absolute pathnames into libc.so and libpthread.so linker
scripts -- absolute pathnames interfere with --sysroot.
cl/51074128 from eglibc-2.18
(ppluzhnikov, google-local)
csu/Makefile
For bit-identical rebuilds, remove `date` invocations.
Forward-ported from cl/51218346 (from cl/37734-p2).
(ppluzhnikov, google-local)
elf/Versions
elf/dl-init.c
sysdeps/i386/elf/start.S
sysdeps/x86_64/elf/start.S
Add __google_auxv.
Forward-ported from cl/51271693 (from cl/38027-p2).
(ppluzhnikov, google-local)
dlfcn/dlmopen.c
dlfcn/dlopen.c
sysdeps/gnu/errlist-compat.awk
Disable static linking warning for dlopen and dlmopen, and disable linking
warning for sys_errlist and sys_nerr.
Forward-ported from cl/51276043 (from part of cl/38025-p2).
(ppluzhnikov, google-local)
include/features.h
Add __GOOGLE_GRTE_VERSION__ for GRTEv4 usage.
Forward-ported with date and comment changed from cl/51277131.
(ppluzhnikov, google-local)
elf/Versions
elf/dl-debug.c
Add _google_dl_debug_state_hook. This is used by libunwind; see comment
in //google3/third_party/grte/google_glibc_extensions.h.
Forward-ported from cl/51330448 (from cl/38429-p2).
(ppluzhnikov, google-local)
include/alloca.h
Set __MAX_ALLOCA_CUTOFF to 8kb to avoid stack overflow, as described in
b/2425017. The stack protection in //google3/thread/thread.cc creates a
large stack with only 64kb of remaining space, which the upstream alloca
heuristic is ill-equipped to deal with.
Forward-ported from cl/51331379 (from cl/38559-p2).
(ppluzhnikov, google-local)
locale/programs/locarchive.c
Reduce starting table sizes for locale-archive file, since we use only a
small fraction of the entries.
Forward-ported from cl/51331729 (from cl/39296-p2).
(cgd, google-local)
sysdeps/unix/grantpt.c
For b/2723095, allow grantpt() to succeed even if it can't chgrp
the slave pty to the "tty" group.
Forward-ported from cl/51332316 (from cl/41538-p2).
(ppluzhnikov, google-local)
elf/rtld.c
For b/4268901, disable "/etc/ld.so.preload", but allow other builds to
re-enable it by setting -DENABLE_ETC_LD_SO_PRELOAD in CFLAGS.
Forward-ported from cl/51332859 (from cl/51576-p2 and cl/51620-p2).
(ppluzhnikov, google-local)
misc/sys/cdefs.h
g/grte-team/browse_thread/thread/d08601e9f5542d94
Disable gcc's __warn_unused_result__ attribute in glibc headers when
_GOOGLE_FORTIFY_SOURCE_NO_WARN_UNUSED_RESULT is specified, even if
_FORTIFY_SOURCE is set. Some google3 code does not compile when this
attribute is set on some glibc functions.
Forward-ported from cl/51334004 (from cl/53404-p2).
(swiecki, google-local)
stdio-common/print_fp.c
stdio-common/print_fphex.c
stdio-common/tstdiomisc.c
Effectively revert an upstream patch to print signs on NaN values. This
change causes many google3 test failures, and the signs are meaningless.
Forward-ported from cl/51376114 (from cl/41709-p2).
(ppluzhnikov, google-local)
posix/glob.c
sysdeps/unix/readdir.c
sysdeps/unix/readdir_r.c
For b/3162458, don't skip files with d_ino==0 -- our tmpfs systems
sometimes create them due to inode wraparound.
Forward-ported from cl/51430993 (from cl/45000-p2).
(ppluzhnikov, google-local)
elf/Makefile
elf/dl-cache.c
elf/dl-support.c
elf/rtld.c
sysdeps/generic/ldsodefs.h
sysdeps/generic/unsecvars.h
For b/2471323, implement multi-level cache search for shared libraries.
Currently, two-level: $prefix/etc/ld.so.conf and /etc/ld.so.conf.
Allow build-time configuration override via GOOGLE_LD_SO_CACHE_LIST.
Allow run-time override via LD_GOOGLE_LD_SO_CACHE_LIST environment
variable.
Forward-ported from cl/51433387 (from cl/38694-p2, cl/38725-p2, and
cl/38741-p2).
(ppluzhnikov, google-local)
elf/dl-cache.c
elf/dl-load.c
include/dlfcn.h
sysdeps/generic/ldsodefs.h
For b/3133396, ignore system ld.so.cache when looking for
nss and iconv modules.
Forward-ported from cl/51433604 (from cl/44863-p2).
(ppluzhnikov, google-local)
nptl/sysdeps/pthread/unwind-forcedunwind.c
For b/5836136, do dlsym(0, "_Unwind..."), i.e. ignore libgcc_s.so.1
dlopen failure.
Forward-ported from cl/51438157.
(ppluzhnikov, google-local)
nptl/Makefile
For b/5013921, build pthread_join.c and pthread_timedjoin.c with
frame pointers.
Forward-ported from cl/51440285 (from cl//54512-p2).
Note: this is redundant with http://cr/62476718 that builds entire glibc
with -fno-omit-frame-pointer, but I am forward-porting it anyway in case
we decide to revert cr/62476718 later.
(ppluzhnikov, google-local)
elf/dl-close.h
elf/dl-load.c
elf/dl-lookup.c
elf/dl-support.c
elf/dl-version.c
elf/rtld.c
sysdeps/generic/ldsodefs.h
Add "fastload" support. This reduces the linear search for symbols when
loading dynamic libraries to a hash-table lookup, dramatically reducing
the startup time of Google3 binaries with large numbers of dynamic-library
dependencies.
Forward-ported from cl/56574617.
(ppluzhnikov, google-local)
sysdeps/unix/sysv/linux/i386/nptl/libc.abilist
sysdeps/unix/sysv/linux/i386/nptl/libnsl.abilist
sysdeps/unix/sysv/linux/x86_64/64/nptl/libc.abilist
sysdeps/unix/sysv/linux/x86_64/64/nptl/libnsl.abilist
Adjust the size value on _nl_default_dirname to match the directory
name that we use in GRTE builds so that "make check-abi" will pass, as
described in the glibc wiki:
http://sourceware.org/glibc/wiki/Testing/Testsuite#Known_testsuite_failures
Also adjust list of exported symbols for google-nsl-stub.
Similar to cr/51166205
(ppluzhnikov, google-local)
Makerules
For b/13350520, disable check-abi
(ppluzhnikov, google-local)
elf/Versions
Export __signal_safe* functions from ld.so so we can use a different
implementation.
(ppluzhnikov, google-local)
elf/dl-dst.h
elf/dl-load.c
elf/dl-support.c
elf/rtld.c
sysdeps/generic/ldsodefs.h
For b/4074041, add EXEC_ORIGIN support.
Forward-ported from cl/56955623 and cl/59961863.
(bmoses, google-local)
nptl/Versions
nptl/pthread_key_create.c
nptl/sysdeps/pthread/pthread.h
nptl/sysdeps/unix/sysv/linux/bits/local_lim.h
nptl/sysdeps/unix/sysv/linux/powerpc/bits/local_lim.h
nptl/sysdeps/unix/sysv/linux/sparc/bits/local_lim.h
nptl/tst-key1.c
nptl/tst-key4.c
ports/sysdeps/unix/sysv/linux/aarch64/nptl/bits/local_lim.h
ports/sysdeps/unix/sysv/linux/alpha/nptl/bits/local_lim.h
ports/sysdeps/unix/sysv/linux/mips/nptl/bits/local_lim.h
ports/sysdeps/unix/sysv/linux/tile/bits/local_lim.h
Add pthread_signal_safe_key_create.
Forward ported from cl/59612021, cl/59817832, and cl/59176280.
(ahh, google-local)
Versions.def
dlfcn/Versions
dlfcn/dlfcn.h
dlfcn/dlmopen.c
dlfcn/dlopen.c
dlfcn/dlopenold.c
elf/dl-deps.c
elf/dl-libc.c
elf/dl-load.c
elf/dl-open.c
elf/rtld.c
include/dlfcn.h
sysdeps/generic/ldsodefs.h
For Google b/8315591, experimental implementation of dlopen_with_offset.
Forward-ported from cl/59286541, cl/59438930
(ppluzhnikov, google-local)
malloc/malloc.c
ports/sysdeps/unix/sysv/linux/aarch64/nptl/localplt.data
sysdeps/generic/localplt.data
sysdeps/unix/sysv/linux/i386/nptl/localplt.data
sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/localplt.data
For b/5732800, expose calls from malloc to mmap, munmap, and sbrk.
Forward ported from cl/42670015, with changes.
(ppluzhnikov, google-local)
elf/rtld.c
For b/12342355, remove inappropriate assert in EXEC_ORIGIN support.
(bmoses, google-local)
sysdeps/powerpc/powerpc32/power4/multiarch/bzero.c
sysdeps/powerpc/powerpc32/power4/multiarch/bzero-ppc32.S
sysdeps/powerpc/powerpc64/multiarch/memset-ppc64.S
For b/14302447, backport upstream patches for __bzero_ppc:
https://sourceware.org/bugzilla/show_bug.cgi?id=16683
https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=4facea473059914983b7da8dd654c06b8e3dcc41
https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=dd3946c615184e1957a0cb09352cac72be5d6d5b
(bmoses, already upstream)
sysdeps/unix/sysv/linux/sys/ptrace.h
For b/13432624, add PTRACE_EVENT_STOP to __ptrace_eventcodes enum.
(bmoses, not yet upstream)
nptl/Makefile
For b/14616463, add -fno-function-sections to events.c compilation.
(bmoses, google-local)
libio/Makefile
libio/fileops.c
libio/iofdopen.c
libio/iofwide.c
libio/libioP.h
libio/tst-ftell-active-handler.c
libio/wfileops.c
For b/15017950, backport upstream patches for PR16532 (separate
ftell, fseek logic) and subsequent optimization and cleanup:
https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=000232b9bcbf194f1e5fd0ff380000f341505405
https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=fa3cd24827d34a49e0a3a5cac56abbf8df74d8ac
https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=091eff71a5edacb5a321c6e573f09a5358540675
https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=d4b17258bba38f206079fbae1e7255779db1b74c
(bmoses, already upstream)
sysdeps/powerpc/powerpc64/fpu/s_copysign.S
For b/13737066, backport upstream patches for PR16786 (s_copysign
stack temp bugfix on PPC ELFv2):
https://sourceware.org/ml/libc-alpha/2014-04/msg00000.html
(bmoses, already upstream)
elf/rtld.c
For b/13901604, set correct __google_auxv before unsetting insecure
environment variables.
(ppluzhnikov, google-local)
posix/spawn_faction_addopen.c
posix/spawn_faction_destroy.c
posix/spawn_int.h
tst-spawn.c
For b/15568332, backport patch to copy path argument to
posix_spawn_file_actions_addopen.
https://sourceware.org/bugzilla/show_bug.cgi?id=17048
(bmoses, backport)
libio/Makefile
libio/iofdopen.c
libio/fileops.c
libio/tst-ftell-active-handler.c
libio/tst-ftell-append.c
libio/wfileops.c
For b/15017950, backport patch to fix offset computation for append+
mode on switching from read, and preceeding patches to fix another
issue with append files and ftell, and to adjust test environments.
https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=ea33158c96c53a64402a772186956c1f5cb556ae
https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=003e49ed5d2034d73bfcf5324c461785687b7e88
https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=2482ae433a4249495859343ae1fba408300f2c2e
https://sourceware.org/bugzilla/show_bug.cgi?id=16724
(bmoses, backport)
misc/mktemp.c
stdio-common/tempnam.c
stdio-common/tmpnam.c
For Crosstool v18 disable link-time warning about mktemp,tempnam and tmpnam.
b/6115789
TODO(ppluzhnikov): revert this after cleanup.
(ppluzhnikov, google-local)
csu/elf-init.c
sysdeps/i386/start.S
sysdeps/x86_64/start.S
For b/13901604, revert local changes to sysdeps/{i386,x86_64}/elf/start.S,
and initialize __google_auxv in __libc_csu_init instead.
(ppluzhnikov, google-local)
csu/elf-init.c
elf/dl-support.c
For b/15780211, revert local change to csu/elf-init.c and move
initialization of __google_auxv earlier (in the fully-static link).
(ppluzhnikov, google-local)
elf/ldd.bash.in
Import ldd patches from Ubuntu source package. This fixes the ability
of ldd to trace dependencies in non-executable dynamic libraries.
(bmoses, google-local)
stdlib/secure-getenv.c
Export a __secure_getenv weak symbol for backwards compatibility at link
time.
(bmoses, google-local)
elf/dl-load.c
include/link.h
For b/18243822, fix dlopen_with_offset to not reuse the same link_map
entry when called on the same file with different offsets.
(ppluzhnikov, google-local)
dlfcn/dlopen.c
elf/dl-load.c
To fix AARCH64 build, make code added to dl-load.c in previous CL
conditional on SHARED. Disable dlopen_with_offet in fully-static links.
(ppluzhnikov, google-local)
wordexp.c
posix/wordexp-test.c
For b/18473397 and CVE-2014-7817, properly handle the WRDE_NOCMD
flag when processing certain arithmetic inputs.
(backport)
https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=a39208bd7fb76c1b01c127b4c61f9bfd915bfe7c
sysdeps/x86_64/start.S
For b/18331558, use ENTRY and END macros to get a .size directive.
(backport)
https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=467fec0bb47464ff49e7075194342b028c75c72f
dlfcn/dlopen.c
Re-fix b/18243822 which got broken by cr/80600560 (AARCH64 build fix).
(ppluzhnikov, google-local)
resolv/res_libc.c
For b/18473393, port r9102, r11566, and r14311 from eglibc sources.
resolv/nss_dns/dns-resolve.c
For b/18752432, backport infinite loop fix in getnetbyname (PR17630)
https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=11e3417af6e354f1942c68a271ae51e892b2814d
stdio-common/tst-sscanf.c
stdio-common/vfscanf.c
For b/19289207, backport memory allocation fix for wscanf (PR16618)
https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=5bd80bfe9ca0d955bfbbc002781bc7b01b6bcb06
socket/sys/un.h
Replace null dereference in the SUN_LEN macro with offsetof.
(nlewycky, not yet upstream)
elf/dl-load.c
For b/8315591, b/20141439 correct off-by-one error that resulted in last
byte of l_name being random garbage.
(ppluzhnikov, google-local)
libio/fmemopen.c
libio/test-fmemopen.c
For b/22167761, backport fix buffer overflow for writes to memory buffer stream (PR18549)
https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=7c2ce714d4e853aadbec13b920576fdfada520f1
(stanshebs, backport)
string/string.h
math/bits/mathcalls.h
misc/sys/cdefs.h
Re-declare hot libc functions with "noplt" attribute available GCC 4.9
onwards. This attribute allows calls to these functions to avoid the
PLT and improves the performance of some of our code via better icache
and iTLB performance.
(tmsriram, google-local)
elf/dl-tls.c
nptl/Makefile
nptl/tst-tls77.c
nptl/tst-tls77mod.c
Fix b/19824366 with tweaks to TLS dynamic loading, and add a test. Note that
upstream commit
https://sourceware.org/git/?p=glibc.git&a=commit&h=f8aeae347377f3dfa8cbadde057adf1827fb1d44
fixes this problem in a different way, so this patch is not needed upstream.
(stanshebs, google-local)
elf/link.h
socket/sys/un.h
Correct locations of __BEGIN_DECLS and #includes, as neeeded for C++
module compatibility.
(chandlerc, google-local)
resolv/nss_dns/dns-host.c
For b/21023324, backport buffer overflow in getanswer_r (PR18287, CVE-2015-1781)
https://sourceware.org/git/?p=glibc.git;a=commit;h=2959eda9272a03386
(stanshebs, backport)
nss/nss_borg/borg-pwd.c
Improve documentation, remove dead code.
(stanshebs, google-local)
posix/fnmatch_loop.c
posix/Makefile
posix/tst-fnmatch3.c
For b/19524869 and b/19533947, backport buffer overflow fixes in fnmatch.
(PR18032, PR18036)
https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=4a28f4d55a6cc33474c0792fe93b5942d81bf185
https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=c2c6d39fab901c97c18fa3a3a3658d9dc3f7df61
(stanshebs, backport)
nss/nss_files/files-XXX.c
nss/Makefile
nss/tst-nss-getpwent.c
For b/19498319, backport fix for nss_files file management (PR18007, CVE-2014-8121)
https://sourceware.org/git/?p=glibc.git;a=commit;h=03d2730b44cc2236318fd978afa2651753666c55
(stanshebs, backport)
elf/dl-load.c
For b/20141439, don't add "foo.so" as alternate name for already loaded foo.so/@0x<offset>
(ppluzhnikov, google-local)
elf/dl-load.c
For b/22641205, #include _itoa.h
(ppluzhnikov, google-local)
nptl/pthread_getspecific.c
nptl/tst-key5.c
Fix for b/18722637 : make pthread_getspecific signal safe.
(ahh, google-local, proposed upstream)
include/resolv.h
resolv/gethnamaddr.c
resolv/res_query.c
resolv/res_send.c
resolv/nss_dns/dns-canon.c
resolv/nss_dns/dns-host.c
resolv/nss_dns/dns-network.c
For b/24580666, backport fix for memory leak in getaddrinfo() (PR16574)
https://sourceware.org/git/?p=glibc.git;a=commit;h=d668061994a7486a3ba9c7d5e7882d85a2883707
https://sourceware.org/git/?p=glibc.git;a=commit;h=ab7ac0f2cf8731fe4c3f3aea6088a7c0127b5725
https://sourceware.org/git/?p=glibc.git;a=commit;h=ab09bf616ad527b249aca5f2a4956fd526f0712f
(stanshebs, backport)
include/features.h
Allow suppressing the definition of __USE_FILE_OFFSET64 by defining
SUPPRESS_USE_FILE_OFFSET64. As large file types match the default
types, this is irrelevant in Google's depot, but leads to different type
signatures for functions that are problematic with C++ modules.
(klimek, google-local)
math/auto-libm-test-in
math/auto-libm-test-out
sysdeps/ieee754/dbl-64/s_sin.c
sysdeps/x86_64/fpu/libm-test-ulps
For b/25873705, backport fix for broken trig functions (PR16623)
https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=1cadc85813d736f7682fa2eeadae639ab6b66c65
(stanshebs, backport)
iconv/gconv_trans.c
For b/25977570, backport removal of __gconv_translit_find (PR17187)
https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=a1a6a401ab0a3c9f15fb7eaebbdcee24192254e8
(stanshebs, backport)
resolv/res_send.c
For b/25900273, adjust allocations to avoid segfault.
(bmoses, google-local)
nptl/allocatestack.c
nptl/Makefile
nptl/tst-basic8.c
For b/24399992 unlock guard pages to avoid wasting memory.
nptl/Makefile
Unbreak building of tst-key5
(stanshebs, google-local)
elf/elf.h
math/libm-test.inc
string/*
sysdeps/ieee754/*
sysdeps/powerpc/*
For b/18010034, backport IBM optimizations for Power8.
https://sourceware.org/git/?p=glibc.git;a=shortlog;h=refs/heads/ibm/2.19/master
(stanshebs, backport)
sysdeps/powerpc/bits/fenvinline.h
For b/27191207, remove use of %s modifier in inline asm.
(stanshebs, google-local)
nptl/sysdeps/unix/sysv/linux/register-atfork.c
For b/28011264, detect and work around loop in fork handler list.
(stanshebs, google-local)
resolv/nss_dns/dns-network.c
For b/27917753, fix stack overflow in _nss_dns_getnetbyname_r (BZ19879)
https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=317b199b4aff8cfa27f2302ab404d2bb5032b9a4
(stanshebs, backport)
resolv/res_send.c
For b/28166767, fix where getaddrinfo() writes DNS queries to random file descriptors
under high load (BZ15946, CVE-2013-7423)
https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=f9d2d03254a58d92635a311a42253eeed5a40a47
(stanshebs, backport)
locale/findlocale.c
locale/setlocale.c
For b/29130905, fix locale vulnerabilities (BZ1737, CVE-2014-0475)
https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=4e8f95a0df7c2300b830ec12c0ae1e161bc8a8a3
https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=d183645616b0533b3acee28f1a95570bffbdf50f
(stanshebs, backport)
nss/nss_cache/nss_cache.h
nss/nss_cache/nss_cache.c
For b/29944535, import current nss_cache.c and nss_cache.h from upstream.
This fixes a performance issue in getgrgid_r on corp machines.
https://github.com/google/libnss-cache/blob/74a14a1dcc669ebe95e90d6d0e0ca36dd8c63b43/nss_cache.c
https://github.com/google/libnss-cache/blob/74a14a1dcc669ebe95e90d6d0e0ca36dd8c63b43/nss_cache.h
(mkanat, google-local)
sysdeps/posix/getaddrinfo.c
For b/30090956, fix stack overflow in hostent conversion (BZ20010, CVE-2016-3706)
https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=4ab2ab03d4351914ee53248dc5aef4a8c88ff8b9
(stanshebs, backport)
sysdeps/posix/getaddrinfo.c
posix/Makefile
posix/tst-getaddrinfo6.c
For b/29615899, fix error handling in getaddrinfo.
(stanshebs, google-local)
elf/elf.h
For b/31273149, revert the value of DT_PPC64_NUM from 4 to 3.
(stanshebs, google-local)
nss/nss_borg/borg-pwd.c
Add /etc/passwd.borg.base as fallback passwd file. (b/30413914, b/32608777)
(mrothwell/stanshebs, google-local)
nss/nss_files/files-XXX.c
For b/26276654, don't ignore too long lines in nss_files (BZ17079, CVE-2015-5277)
https://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commit;h=3fd498242948b1fa944c56646ec9b156387dd310
(stanshebs, backport)
posix/fnmatch_loop.c
Don't read past end of pattern in fnmatch (BZ17062)
https://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commit;h=b3a9f56ba59c3d8eadd3135a1c25c37a63151450
(stanshebs, backport)
nss/tst-nss-getpwent.c
Work around b/34251679 by restricting to nss_files module
(stanshebs, google-local)
time/strftime_l.c
time/tst-strftime.c
Fix where out of range data to strftime() causes a segfault (BZ18985, CVE-2015-8776)
https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=d36c75fc0d44deec29635dd239b0fbd206ca49b7
(stanshebs, backport)
elf/rtld.c
sysdeps/generic/ldsodefs.h
Always enable pointer guard (BZ18928, CVE-2015-8777)
https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=a014cecd82b71b70a6a843e250e06b541ad524f7
(stanshebs, backport)
misc/Makefile
misc/bug18240.c
misc/hsearch_r.c
hcreate, hcreate_r should fail with ENOMEM if element count is too large (BZ18240, CVE-2015-8778)
https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=b5cba5cff937e5336ff23380785da80cab09146c
https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=3c9e8d9477aba0f514171bb4706670052544479b
(stanshebs, backport)
catgets/Makefile
catgets/catgets.c
catgets/open_catalog.c
catgets/tst-catgets.c
Fix catopen() Multiple unbounded stack allocations (BZ17905, CVE-2015-8779)
https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=0f58539030e436449f79189b6edab17d7479796e
(stanshebs, backport)
ports/sysdeps/unix/sysv/linux/arm/setcontext.S
Missing unwind info in __startcontext causes infinite loop (BZ20435, CVE-2016-6323)
https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=9e2ff6c9cc54c0b4402b8d49e4abe7000fde7617
(stanshebs, backport)
include/stdlib.h
include/wchar.h
math/Makefile
math/s_nan.c
math/s_nanf.c
math/s_nanl.c
math/test-nan-overflow.c
math/test-nan-payload.c
stdlib/Makefile
stdlib/Versions
stdlib/strtod_l.c
stdlib/strtod_nan.c
stdlib/strtod_nan_double.h
stdlib/strtod_nan_float.h
stdlib/strtod_nan_main.c
stdlib/strtod_nan_narrow.h
stdlib/strtod_nan_wide.h
stdlib/strtof_l.c
stdlib/strtof_nan.c
stdlib/strtold_nan.c
sysdeps/ieee754/ldbl-128/strtod_nan_ldouble.h
sysdeps/ieee754/ldbl-128/strtold_l.c
sysdeps/ieee754/ldbl-128ibm/strtod_nan_ldouble.h
sysdeps/ieee754/ldbl-128ibm/strtold_l.c
sysdeps/ieee754/ldbl-64-128/strtold_l.c
sysdeps/ieee754/ldbl-96/strtod_nan_ldouble.h
sysdeps/ieee754/ldbl-96/strtold_l.c
wcsmbs/Makefile
wcsmbs/wcstod_l.c
wcsmbs/wcstod_nan.c
wcsmbs/wcstof_l.c
wcsmbs/wcstof_nan.c
wcsmbs/wcstold_l.c
wcsmbs/wcstold_nan.c
Fix nan functions handling of payload strings (BZ16962, CVE-2014-9761)
https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=e02cabecf0d025ec4f4ddee290bdf7aadb873bb3
https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=8f5e8b01a1da2a207228f2072c934fa5918554b8
(stanshebs, backport)
+7
View File
@@ -50,6 +50,7 @@ libdl {
GLIBC_2.1
GLIBC_2.3.3
GLIBC_2.3.4
GLIBC_2.15
}
libm {
GLIBC_2.0
@@ -80,6 +81,12 @@ libnss_db {
libnss_files {
GLIBC_PRIVATE
}
libnss_borg {
GLIBC_PRIVATE
}
libnss_cache {
GLIBC_PRIVATE
}
libnss_hesiod {
GLIBC_PRIVATE
}
+6 -2
View File
@@ -46,13 +46,14 @@ CPPFLAGS-gencat = -DNOT_IN_libc
generated = de.msg test1.cat test1.h test2.cat test2.h sample.SJIS.cat \
test-gencat.h
generated += tst-catgets.mtrace tst-catgets-mem.out
generated-dirs = de
tst-catgets-ENV = NLSPATH="$(objpfx)%l/%N.cat" LANG=de
tst-catgets-ENV = NLSPATH="$(objpfx)%l/%N.cat" LANG=de MALLOC_TRACE=$(objpfx)tst-catgets.mtrace
ifeq ($(run-built-tests),yes)
tests: $(objpfx)de/libc.cat $(objpfx)test1.cat $(objpfx)test2.cat \
$(objpfx)test-gencat.out
$(objpfx)test-gencat.out $(objpfx)tst-catgets-mem.out
# This test just checks whether the program produces any error or not.
# The result is not tested.
$(objpfx)test1.cat: test1.msg $(objpfx)gencat
@@ -80,4 +81,7 @@ $(objpfx)test-gencat.out: test-gencat.sh $(objpfx)test-gencat \
$(objpfx)sample.SJIS.cat: sample.SJIS $(objpfx)gencat
GCONV_PATH=$(common-objpfx)iconvdata LC_ALL=C \
$(built-program-cmd) -H $(objpfx)test-gencat.h < $(word 1,$^) > $@
$(objpfx)tst-catgets-mem.out: $(objpfx)tst-catgets.out
$(common-objpfx)malloc/mtrace $(objpfx)tst-catgets.mtrace > $@
endif
+12 -7
View File
@@ -16,7 +16,6 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <alloca.h>
#include <errno.h>
#include <locale.h>
#include <nl_types.h>
@@ -35,6 +34,7 @@ catopen (const char *cat_name, int flag)
__nl_catd result;
const char *env_var = NULL;
const char *nlspath = NULL;
char *tmp = NULL;
if (strchr (cat_name, '/') == NULL)
{
@@ -54,7 +54,10 @@ catopen (const char *cat_name, int flag)
{
/* Append the system dependent directory. */
size_t len = strlen (nlspath) + 1 + sizeof NLSPATH;
char *tmp = alloca (len);
tmp = malloc (len);
if (__glibc_unlikely (tmp == NULL))
return (nl_catd) -1;
__stpcpy (__stpcpy (__stpcpy (tmp, nlspath), ":"), NLSPATH);
nlspath = tmp;
@@ -65,16 +68,18 @@ catopen (const char *cat_name, int flag)
result = (__nl_catd) malloc (sizeof (*result));
if (result == NULL)
/* We cannot get enough memory. */
return (nl_catd) -1;
if (__open_catalog (cat_name, nlspath, env_var, result) != 0)
{
/* We cannot get enough memory. */
result = (nl_catd) -1;
}
else if (__open_catalog (cat_name, nlspath, env_var, result) != 0)
{
/* Couldn't open the file. */
free ((void *) result);
return (nl_catd) -1;
result = (nl_catd) -1;
}
free (tmp);
return (nl_catd) result;
}
+14 -9
View File
@@ -47,6 +47,7 @@ __open_catalog (const char *cat_name, const char *nlspath, const char *env_var,
size_t tab_size;
const char *lastp;
int result = -1;
char *buf = NULL;
if (strchr (cat_name, '/') != NULL || nlspath == NULL)
fd = open_not_cancel_2 (cat_name, O_RDONLY);
@@ -57,23 +58,23 @@ __open_catalog (const char *cat_name, const char *nlspath, const char *env_var,
if (__builtin_expect (bufact + (n) >= bufmax, 0)) \
{ \
char *old_buf = buf; \
bufmax += 256 + (n); \
buf = (char *) alloca (bufmax); \
memcpy (buf, old_buf, bufact); \
bufmax += (bufmax < 256 + (n)) ? 256 + (n) : bufmax; \
buf = realloc (buf, bufmax); \
if (__glibc_unlikely (buf == NULL)) \
{ \
free (old_buf); \
return -1; \
} \
}
/* The RUN_NLSPATH variable contains a colon separated list of
descriptions where we expect to find catalogs. We have to
recognize certain % substitutions and stop when we found the
first existing file. */
char *buf;
size_t bufact;
size_t bufmax;
size_t bufmax = 0;
size_t len;
buf = NULL;
bufmax = 0;
fd = -1;
while (*run_nlspath != '\0')
{
@@ -188,7 +189,10 @@ __open_catalog (const char *cat_name, const char *nlspath, const char *env_var,
/* Avoid dealing with directories and block devices */
if (__builtin_expect (fd, 0) < 0)
return -1;
{
free (buf);
return -1;
}
if (__builtin_expect (__fxstat64 (_STAT_VER, fd, &st), 0) < 0)
goto close_unlock_return;
@@ -325,6 +329,7 @@ __open_catalog (const char *cat_name, const char *nlspath, const char *env_var,
/* Release the lock again. */
close_unlock_return:
close_not_cancel_no_status (fd);
free (buf);
return result;
}
+31
View File
@@ -1,7 +1,10 @@
#include <assert.h>
#include <mcheck.h>
#include <nl_types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/resource.h>
static const char *msgs[] =
@@ -12,6 +15,33 @@ static const char *msgs[] =
};
#define nmsgs (sizeof (msgs) / sizeof (msgs[0]))
/* Test for unbounded alloca. */
static int
do_bz17905 (void)
{
char *buf;
struct rlimit rl;
nl_catd result;
const int sz = 1024 * 1024;
getrlimit (RLIMIT_STACK, &rl);
rl.rlim_cur = sz;
setrlimit (RLIMIT_STACK, &rl);
buf = malloc (sz + 1);
memset (buf, 'A', sz);
buf[sz] = '\0';
setenv ("NLSPATH", buf, 1);
result = catopen (buf, NL_CAT_LOCALE);
assert (result == (nl_catd) -1);
free (buf);
return 0;
}
#define ROUNDS 5
int
@@ -62,5 +92,6 @@ main (void)
}
}
result += do_bz17905 ();
return result;
}
+4 -2
View File
@@ -162,8 +162,10 @@ $(objpfx)version-info.h: $(common-objpfx)config.make $(all-Banner-files)
if [ -z "$$os" ]; then \
os=Linux; \
fi; \
printf '"Compiled on a %s %s system on %s.\\n"\n' \
"$$os" "$$version" "`date +%Y-%m-%d`";; \
# GOOGLE LOCAL: removed 'on %s' and '"`date +%Y-%m-%d`"' \
# to enable bit-identical rebuilds \
printf '"Compiled on a %s %s system.\\n"\n' \
"$$os" "$$version";; \
*) ;; \
esac; \
files="$(all-Banner-files)"; \
+2
View File
@@ -35,6 +35,8 @@
#include <stddef.h>
# include <link.h> // For ElfW.
/* These magic symbols are provided by the linker. */
extern void (*__preinit_array_start []) (int, char **, char **)
+3
View File
@@ -11,6 +11,9 @@ libdl {
GLIBC_2.3.4 {
dlmopen;
}
GLIBC_2.15 {
__google_dlopen_with_offset; __google_dlmopen_with_offset;
}
GLIBC_PRIVATE {
_dlfcn_hook;
}
+12
View File
@@ -22,6 +22,7 @@
#include <features.h>
#define __need_size_t
#include <stddef.h>
#include <sys/types.h>
/* Collect various system dependent definitions and declarations. */
#include <bits/dlfcn.h>
@@ -55,6 +56,11 @@ __BEGIN_DECLS
passed to `dlsym' to get symbol values from it. */
extern void *dlopen (const char *__file, int __mode) __THROWNL;
/* Same as above, but ELF header is at OFF from the start of file. */
extern void *__google_dlopen_with_offset (__const char *__file,
off_t offset,
int __mode) __THROW;
/* Unmap and close a shared object opened by `dlopen'.
The handle cannot be used again after calling `dlclose'. */
extern int dlclose (void *__handle) __THROWNL __nonnull ((1));
@@ -68,6 +74,12 @@ extern void *dlsym (void *__restrict __handle,
/* Like `dlopen', but request object to be allocated in a new namespace. */
extern void *dlmopen (Lmid_t __nsid, const char *__file, int __mode) __THROWNL;
/* Same as above, but ELF header is at OFF from the start of file. */
extern void *__google_dlmopen_with_offset (Lmid_t __nsid,
__const char *__file,
off_t offset,
int __mode) __THROW;
/* Find the run-time address in the shared object HANDLE refers to
of the symbol called NAME with VERSION. */
extern void *dlvsym (void *__restrict __handle,
+49 -12
View File
@@ -30,7 +30,9 @@ dlmopen (Lmid_t nsid, const char *file, int mode)
{
return __dlmopen (nsid, file, mode, RETURN_ADDRESS (0));
}
#if 0 // Google-local
static_link_warning (dlmopen)
#endif
#else
@@ -38,6 +40,8 @@ struct dlmopen_args
{
/* Namespace ID. */
Lmid_t nsid;
/* ELF header at offset in file. */
off_t offset;
/* The arguments for dlopen_doit. */
const char *file;
int mode;
@@ -68,13 +72,55 @@ dlmopen_doit (void *a)
GLRO(dl_signal_error) (EINVAL, NULL, NULL, N_("invalid mode"));
}
args->new = GLRO(dl_open) (args->file ?: "", args->mode | __RTLD_DLOPEN,
args->new = GLRO(dl_open) (args->file ?: "",
args->offset,
args->mode | __RTLD_DLOPEN,
args->caller,
args->nsid, __dlfcn_argc, __dlfcn_argv,
__environ);
}
static void *
__dlmopen_common (struct dlmopen_args *args)
{
# ifdef SHARED
return _dlerror_run (dlmopen_doit, args) ? NULL : args->new;
# else
if (_dlerror_run (dlmopen_doit, args))
return NULL;
__libc_register_dl_open_hook ((struct link_map *) args->new);
__libc_register_dlfcn_hook ((struct link_map *) args->new);
return args->new;
# endif
}
void *
__dlmopen_with_offset (Lmid_t nsid, const char *file, off_t offset,
int mode DL_CALLER_DECL)
{
# ifdef SHARED
if (__builtin_expect (_dlfcn_hook != NULL, 0))
return _dlfcn_hook->dlmopen_with_offset (nsid, file, offset,
mode, RETURN_ADDRESS (0));
# endif
struct dlmopen_args args;
args.nsid = nsid;
args.file = file;
args.offset = offset;
args.mode = mode;
args.caller = DL_CALLER;
return __dlmopen_common (&args);
}
# ifdef SHARED
strong_alias (__dlmopen_with_offset, __google_dlmopen_with_offset)
# endif
void *
__dlmopen (Lmid_t nsid, const char *file, int mode DL_CALLER_DECL)
{
@@ -86,20 +132,11 @@ __dlmopen (Lmid_t nsid, const char *file, int mode DL_CALLER_DECL)
struct dlmopen_args args;
args.nsid = nsid;
args.file = file;
args.offset = 0;
args.mode = mode;
args.caller = DL_CALLER;
# ifdef SHARED
return _dlerror_run (dlmopen_doit, &args) ? NULL : args.new;
# else
if (_dlerror_run (dlmopen_doit, &args))
return NULL;
__libc_register_dl_open_hook ((struct link_map *) args.new);
__libc_register_dlfcn_hook ((struct link_map *) args.new);
return args.new;
# endif
return __dlmopen_common (&args);
}
# ifdef SHARED
strong_alias (__dlmopen, dlmopen)
+43 -12
View File
@@ -29,7 +29,9 @@ dlopen (const char *file, int mode)
{
return __dlopen (file, mode, RETURN_ADDRESS (0));
}
#if 0 // Google-local
static_link_warning (dlopen)
#endif
#else
@@ -37,6 +39,8 @@ struct dlopen_args
{
/* The arguments for dlopen_doit. */
const char *file;
/* ELF header at offset in file. */
off_t offset;
int mode;
/* The return value of dlopen_doit. */
void *new;
@@ -63,13 +67,49 @@ dlopen_doit (void *a)
| __RTLD_SPROF))
GLRO(dl_signal_error) (0, NULL, NULL, _("invalid mode parameter"));
args->new = GLRO(dl_open) (args->file ?: "", args->mode | __RTLD_DLOPEN,
args->new = GLRO(dl_open) (args->file ?: "",
args->offset,
args->mode | __RTLD_DLOPEN,
args->caller,
args->file == NULL ? LM_ID_BASE : NS,
__dlfcn_argc, __dlfcn_argv, __environ);
}
static void *
__dlopen_common (struct dlopen_args *args)
{
# ifdef SHARED
return _dlerror_run (dlopen_doit, args) ? NULL : args->new;
# else
if (_dlerror_run (dlopen_doit, args))
return NULL;
__libc_register_dl_open_hook ((struct link_map *) args->new);
__libc_register_dlfcn_hook ((struct link_map *) args->new);
return args->new;
# endif
}
# ifdef SHARED
void *
__dlopen_with_offset (const char *file, off_t offset, int mode DL_CALLER_DECL)
{
if (__builtin_expect (_dlfcn_hook != NULL, 0))
return _dlfcn_hook->dlopen_with_offset (file, offset, mode, DL_CALLER);
struct dlopen_args args;
args.file = file;
args.offset = offset;
args.mode = mode;
args.caller = DL_CALLER;
return __dlopen_common (&args);
}
strong_alias (__dlopen_with_offset, __google_dlopen_with_offset)
# endif
void *
__dlopen (const char *file, int mode DL_CALLER_DECL)
{
@@ -80,20 +120,11 @@ __dlopen (const char *file, int mode DL_CALLER_DECL)
struct dlopen_args args;
args.file = file;
args.offset = 0;
args.mode = mode;
args.caller = DL_CALLER;
# ifdef SHARED
return _dlerror_run (dlopen_doit, &args) ? NULL : args.new;
# else
if (_dlerror_run (dlopen_doit, &args))
return NULL;
__libc_register_dl_open_hook ((struct link_map *) args.new);
__libc_register_dlfcn_hook ((struct link_map *) args.new);
return args.new;
# endif
return __dlopen_common (&args);
}
# ifdef SHARED
# include <shlib-compat.h>
+1 -1
View File
@@ -51,7 +51,7 @@ dlopen_doit (void *a)
{
struct dlopen_args *args = (struct dlopen_args *) a;
args->new = GLRO(dl_open) (args->file ?: "", args->mode | __RTLD_DLOPEN,
args->new = GLRO(dl_open) (args->file ?: "", 0, args->mode | __RTLD_DLOPEN,
args->caller,
args->file == NULL ? LM_ID_BASE : NS,
__dlfcn_argc, __dlfcn_argv, __environ);
+1
View File
@@ -422,6 +422,7 @@ CFLAGS-ldconfig.c = $(SYSCONF-FLAGS) -D'LIBDIR="$(libdir)"' \
CFLAGS-dl-cache.c = $(SYSCONF-FLAGS)
CFLAGS-cache.c = $(SYSCONF-FLAGS)
CFLAGS-rtld.c = $(SYSCONF-FLAGS)
CFLAGS-dl-support.c = $(SYSCONF-FLAGS)
CPPFLAGS-.os += $(if $(filter $(@F),$(patsubst %,%.os,$(all-rtld-routines))),\
-DNOT_IN_libc=1 -DIS_IN_rtld=1 -DIN_LIB=rtld)
+13
View File
@@ -53,6 +53,7 @@ ld {
_dl_allocate_tls; _dl_allocate_tls_init;
_dl_argv; _dl_find_dso_for_object; _dl_get_tls_static_info;
_dl_deallocate_tls; _dl_make_stack_executable; _dl_out_of_memory;
_dl_clear_dtv;
_dl_rtld_di_serinfo; _dl_starting_up; _dl_tls_setup;
_rtld_global; _rtld_global_ro;
@@ -61,5 +62,17 @@ ld {
# Pointer protection.
__pointer_chk_guard;
# Google-local
_google_dl_debug_state_hook;
__google_auxv;
# Expose __signal_safe* functions so we can use a different
# implementation (Google-local)
__signal_safe_calloc;
__signal_safe_free;
__signal_safe_malloc;
__signal_safe_memalign;
__signal_safe_realloc;
}
}
+148 -41
View File
@@ -29,10 +29,19 @@
# define _DL_PLATFORMS_COUNT 0
#endif
/* 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;
/* This struct describes a single ld.so.cache (there could be several,
as we want to look in $prefix/etc/ld.so.cache and in the system default
/etc/ld.so.cache). See b/2471323. */
struct cache_info {
const char *ld_so_cache;
/* This is the starting address and the size of the mmap()ed file. */
struct cache_file *cache;
struct cache_file_new *cache_new;
size_t cachesize;
};
/* Dynamically allocated; last entry is sentinel with ld_so_cache == NULL. */
static struct cache_info *cache_info;
/* 1 if cache_data + PTR points into the cache. */
#define _dl_cache_verify_ptr(ptr) (ptr < cache_data_size)
@@ -172,13 +181,14 @@ _dl_cache_libcmp (const char *p1, const char *p2)
}
/* 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
the cache previously failed there will be no more attempts to load it. */
/* Look up NAME in ld.so.cache described by INFO and return the file name
stored there, or null if none is found. The cache is loaded if it was not
already. If loading the cache previously failed there will be no more
attempts to load it. */
static
const char *
internal_function
_dl_load_cache_lookup (const char *name)
_dl_load_cache_lookup_2 (const char *name, struct cache_info *info)
{
int left, right, middle;
int cmpres;
@@ -188,12 +198,13 @@ _dl_load_cache_lookup (const char *name)
/* Print a message if the loading of libs is traced. */
if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_LIBS, 0))
_dl_debug_printf (" search cache=%s\n", LD_SO_CACHE);
_dl_debug_printf (" search cache=%s\n", info->ld_so_cache);
if (cache == NULL)
if (info->cache == NULL)
{
/* Read the contents of the file. */
void *file = _dl_sysdep_read_whole_file (LD_SO_CACHE, &cachesize,
void *file = _dl_sysdep_read_whole_file (info->ld_so_cache,
&info->cachesize,
PROT_READ);
/* We can handle three different cache file formats here:
@@ -201,55 +212,58 @@ _dl_load_cache_lookup (const char *name)
- the old format with the new format in it
- only the new format
The following checks if the cache contains any of these formats. */
if (file != MAP_FAILED && cachesize > sizeof *cache
if (file != MAP_FAILED && info->cachesize > sizeof *info->cache
&& memcmp (file, CACHEMAGIC, sizeof CACHEMAGIC - 1) == 0)
{
size_t offset;
/* Looks ok. */
cache = file;
info->cache = file;
/* Check for new version. */
offset = ALIGN_CACHE (sizeof (struct cache_file)
+ cache->nlibs * sizeof (struct file_entry));
offset =
ALIGN_CACHE (sizeof (struct cache_file)
+ info->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,
info->cache_new =
(struct cache_file_new *) ((void *) info->cache + offset);
if (info->cachesize < (offset + sizeof (struct cache_file_new))
|| memcmp (info->cache_new->magic, CACHEMAGIC_VERSION_NEW,
sizeof CACHEMAGIC_VERSION_NEW - 1) != 0)
cache_new = (void *) -1;
info->cache_new = (void *) -1;
}
else if (file != MAP_FAILED && cachesize > sizeof *cache_new
else if (file != MAP_FAILED && info->cachesize > sizeof *info->cache_new
&& memcmp (file, CACHEMAGIC_VERSION_NEW,
sizeof CACHEMAGIC_VERSION_NEW - 1) == 0)
{
cache_new = file;
cache = file;
info->cache_new = file;
info->cache = file;
}
else
{
if (file != MAP_FAILED)
__munmap (file, cachesize);
cache = (void *) -1;
__munmap (file, info->cachesize);
info->cache = (void *) -1;
}
assert (cache != NULL);
assert (info->cache != NULL);
}
if (cache == (void *) -1)
if (info->cache == (void *) -1)
/* Previously looked for the cache file and didn't find it. */
return NULL;
best = NULL;
if (cache_new != (void *) -1)
if (info->cache_new != (void *) -1)
{
uint64_t platform;
/* This is where the strings start. */
cache_data = (const char *) cache_new;
cache_data = (const char *) info->cache_new;
/* Now we can compute how large the string table is. */
cache_data_size = (const char *) cache + cachesize - cache_data;
cache_data_size =
(const char *) info->cache + info->cachesize - cache_data;
platform = _dl_string_platform (GLRO(dl_platform));
if (platform != (uint64_t) -1)
@@ -269,19 +283,20 @@ _dl_load_cache_lookup (const char *name)
&& (lib->hwcap & _DL_HWCAP_PLATFORM) != 0 \
&& (lib->hwcap & _DL_HWCAP_PLATFORM) != platform) \
continue
SEARCH_CACHE (cache_new);
SEARCH_CACHE (info->cache_new);
}
else
{
/* This is where the strings start. */
cache_data = (const char *) &cache->libs[cache->nlibs];
cache_data = (const char *) &info->cache->libs[info->cache->nlibs];
/* Now we can compute how large the string table is. */
cache_data_size = (const char *) cache + cachesize - cache_data;
cache_data_size =
(const char *) info->cache + info->cachesize - cache_data;
#undef HWCAP_CHECK
#define HWCAP_CHECK do {} while (0)
SEARCH_CACHE (cache);
SEARCH_CACHE (info->cache);
}
/* Print our result if wanted. */
@@ -292,18 +307,110 @@ _dl_load_cache_lookup (const char *name)
return best;
}
/* Parse CACHE_LIST, and build cache_info array. */
static
struct cache_info *
_dl_alloc_cache_info (const char *const cache_list)
{
struct cache_info *info;
const char *begin;
int num_caches, i;
begin = cache_list;
num_caches = 0;
/* cache_list is a colon-separated list of absolute pathnames of
ld.so.cache files. We stop at first non-absolute path (if any). */
while (begin[0] == '/')
{
++num_caches;
begin = strchr (begin, ':');
if (begin == NULL)
break;
++begin;
}
/* Allocate one extra for the sentinel. */
info = (struct cache_info *) calloc (num_caches + 1, sizeof (*cache_info));
begin = cache_list;
for (i = 0; i < num_caches; ++i)
{
const char *const end = strchr(begin, ':');
if (end == NULL)
info[i].ld_so_cache = strdup (begin);
else
{
info[i].ld_so_cache = strndup (begin, end - begin);
begin = end + 1;
}
}
return info;
}
/* Look up NAME in each of ld.so.cache caches in turn, and return the
file name stored there, or null if none is found. */
const char *
internal_function
_dl_load_cache_lookup (const char *name, int mode)
{
struct cache_info *info;
/* This runs at startup, or during dlopen with loader lock held. */
if (cache_info == NULL)
/* Caches have not been initialized yet. */
cache_info = _dl_alloc_cache_info (GLRO(google_ld_so_cache_list));
if (mode & __RTLD_GOOGLE_IGNORE_HOST_LD_SO_CACHE)
{
/* We are loading a component of glibc itself (e.g. nss or iconv).
Such components must not be loaded from host, only from this
glibc compilation (which must always be the first component of
the cache list). See b/3133396 */
return _dl_load_cache_lookup_2 (name, cache_info);
}
for (info = cache_info; info->ld_so_cache != NULL; ++info)
{
const char *result;
result = _dl_load_cache_lookup_2 (name, info);
if (result != NULL)
return result;
}
return NULL;
}
#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. */
Therefore we provide this function to close the file described by INFO
and open it again once needed. */
static
void
_dl_unload_cache_2 (struct cache_info *info)
{
if (info->cache != NULL && info->cache != (struct cache_file *) -1)
{
__munmap (info->cache, info->cachesize);
info->cache = NULL;
}
}
/* Unload all loaded ld.so.cache caches. */
void
_dl_unload_cache (void)
{
if (cache != NULL && cache != (struct cache_file *) -1)
{
__munmap (cache, cachesize);
cache = NULL;
}
struct cache_info *info;
if (cache_info == NULL)
/* No caches loaded yet. */
return;
for (info = cache_info; info->ld_so_cache != NULL; ++info)
_dl_unload_cache_2 (info);
}
#endif
+6
View File
@@ -133,6 +133,12 @@ _dl_close_worker (struct link_map *map)
Lmid_t nsid = map->l_ns;
struct link_namespaces *ns = &GL(dl_ns)[nsid];
/* Recompute _ns_last next time we need it.
It is tempting to set _ns_last to map->l_prev, but map->l_prev might also
be going away as part of current dlclose, and using it may cause _ns_last
to become dangling. */
ns->_ns_last = NULL;
retry:
dl_close_state = pending;
+4
View File
@@ -65,6 +65,8 @@ _dl_debug_initialize (ElfW(Addr) ldbase, Lmid_t ns)
}
void (*_google_dl_debug_state_hook)(const struct r_debug *);
/* This function exists solely to have a breakpoint set on it by the
debugger. The debugger is supposed to find this function's address by
examining the r_brk member of struct r_debug, but GDB 4.15 in fact looks
@@ -72,5 +74,7 @@ _dl_debug_initialize (ElfW(Addr) ldbase, Lmid_t ns)
void
_dl_debug_state (void)
{
if (_google_dl_debug_state_hook)
_google_dl_debug_state_hook(&_r_debug);
}
rtld_hidden_def (_dl_debug_state)
+1 -1
View File
@@ -60,7 +60,7 @@ openaux (void *a)
{
struct openaux_args *args = (struct openaux_args *) a;
args->aux = _dl_map_object (args->map, args->name,
args->aux = _dl_map_object (args->map, args->name, 0,
(args->map->l_type == lt_executable
? lt_library : args->map->l_type),
args->trace_mode, args->open_mode,
+7 -2
View File
@@ -65,8 +65,13 @@
else \
dst_len = (l)->l_origin == (char *) -1 \
? 0 : strlen ((l)->l_origin); \
dst_len = MAX (MAX (dst_len, GLRO(dl_platformlen)), \
strlen (DL_DST_LIB)); \
\
char *exec_origin = GLRO(google_exec_origin_dir); \
size_t exec_origin_len = \
(exec_origin == NULL) ? 0 : strlen (exec_origin); \
\
dst_len = MAX (MAX (MAX (dst_len, GLRO(dl_platformlen)), \
strlen (DL_DST_LIB)), exec_origin_len); \
if (dst_len > 4) \
__len += __cnt * (dst_len - 4); \
} \
+13
View File
@@ -80,6 +80,8 @@ call_init (struct link_map *l, int argc, char **argv, char **env)
}
ElfW(auxv_t) *__google_auxv;
void
internal_function
_dl_init (struct link_map *main_map, int argc, char **argv, char **env)
@@ -88,6 +90,17 @@ _dl_init (struct link_map *main_map, int argc, char **argv, char **env)
ElfW(Dyn) *preinit_array_size = main_map->l_info[DT_PREINIT_ARRAYSZ];
unsigned int i;
/* _dl_init is called from _dl_start_user during loader startup.
It is also called from dl_open_worker.
Prevent multiple initialization of __google_auxv. */
if (__google_auxv == NULL)
{
char **e;
for (e = env; *e; ++e) /* Skip. */;
__google_auxv = (ElfW(auxv_t) *) ++e;
}
if (__builtin_expect (GL(dl_initfirst) != NULL, 0))
{
call_init (GL(dl_initfirst), argc, argv, env);
+5 -3
View File
@@ -59,6 +59,7 @@ struct do_dlopen_args
{
/* Argument to do_dlopen. */
const char *name;
off_t offset;
/* Opening mode. */
int mode;
/* This is the caller of the dlopen() function. */
@@ -84,9 +85,9 @@ do_dlopen (void *ptr)
{
struct do_dlopen_args *args = (struct do_dlopen_args *) ptr;
/* Open and relocate the shared object. */
args->map = GLRO(dl_open) (args->name, args->mode, args->caller_dlopen,
__LM_ID_CALLER, __libc_argc, __libc_argv,
__environ);
args->map = GLRO(dl_open) (args->name, args->offset, args->mode,
args->caller_dlopen, __LM_ID_CALLER,
__libc_argc, __libc_argv, __environ);
}
static void
@@ -154,6 +155,7 @@ __libc_dlopen_mode (const char *name, int mode)
{
struct do_dlopen_args args;
args.name = name;
args.offset = 0;
args.mode = mode;
args.caller_dlopen = RETURN_ADDRESS (0);
+113 -47
View File
@@ -38,6 +38,7 @@
#include <stap-probe.h>
#include <dl-dst.h>
#include <_itoa.h>
/* On some systems, no flag bits are given to specify file mapping. */
#ifndef MAP_FILE
@@ -306,7 +307,8 @@ _dl_dst_count (const char *name, int is_path)
if ((len = is_dst (start, name, "ORIGIN", is_path,
INTUSE(__libc_enable_secure))) != 0
|| (len = is_dst (start, name, "PLATFORM", is_path, 0)) != 0
|| (len = is_dst (start, name, "LIB", is_path, 0)) != 0)
|| (len = is_dst (start, name, "LIB", is_path, 0)) != 0
|| (len = is_dst (start, name, "EXEC_ORIGIN", is_path, 0)) != 0)
++cnt;
name = strchr (name + len, '$');
@@ -350,6 +352,13 @@ _dl_dst_substitute (struct link_map *l, const char *name, char *result,
repl = GLRO(dl_platform);
else if ((len = is_dst (start, name, "LIB", is_path, 0)) != 0)
repl = DL_DST_LIB;
else if ((len = is_dst (start, name, "EXEC_ORIGIN", is_path, 0)) != 0)
{
if (INTUSE(__libc_enable_secure) != 0)
_dl_fatal_printf ("$EXEC_ORIGIN rpath entry not allowed in setuid/setgid executables.\n");
repl = GLRO(google_exec_origin_dir);
}
if (repl != NULL && repl != (const char *) -1)
{
@@ -917,7 +926,8 @@ lose (int code, int fd, const char *name, char *realname, struct link_map *l,
static
#endif
struct link_map *
_dl_map_object_from_fd (const char *name, int fd, struct filebuf *fbp,
_dl_map_object_from_fd (const char *name, int fd, off_t offset,
struct filebuf *fbp,
char *realname, struct link_map *loader, int l_type,
int mode, void **stack_endp, Lmid_t nsid)
{
@@ -947,7 +957,8 @@ _dl_map_object_from_fd (const char *name, int fd, struct filebuf *fbp,
/* Look again to see if the real name matched another already loaded. */
for (l = GL(dl_ns)[nsid]._ns_loaded; l; l = l->l_next)
if (l->l_removed == 0 && l->l_ino == st.st_ino && l->l_dev == st.st_dev)
if (l->l_removed == 0 && l->l_ino == st.st_ino && l->l_dev == st.st_dev
&& l->l_off == offset)
{
/* The object is already loaded.
Just bump its reference count and return it. */
@@ -956,7 +967,10 @@ _dl_map_object_from_fd (const char *name, int fd, struct filebuf *fbp,
/* If the name is not in the list of names for this object add
it. */
free (realname);
add_name_to_object (l, name);
if (offset == 0)
/* If offset!=0, foo.so/@0x<offset> should be the *only*
name for this object. b/20141439. */
add_name_to_object (l, name);
return l;
}
@@ -1055,8 +1069,30 @@ _dl_map_object_from_fd (const char *name, int fd, struct filebuf *fbp,
else
assert (r->r_state == RT_ADD);
#ifdef SHARED
// This code could be linked into 'sln', which does not have _itoa.
// We only care about this when this is linked into ld-linux.
if (offset != 0)
{
/* Google-specific: to help GDB, and for b/18243822, turn realname
into "realname/@0x<offset>" */
realname = realloc (realname, strlen(realname) + 16 + 4 /* "/@0x" */);
if (realname == NULL)
{
errstring = N_("unable to realloc");
goto call_lose_errno;
}
strcat(realname, "/@0x");
char tmp[20];
tmp[19] = '\0';
strcat(realname, _itoa(offset, &tmp[19], 16, 0));
}
#endif
/* Enter the new object in the list of loaded objects. */
l = _dl_new_object (realname, name, l_type, loader, mode, nsid);
l = _dl_new_object (realname, offset ? realname : name, l_type,
loader, mode, nsid);
if (__builtin_expect (l == NULL, 0))
{
#ifdef SHARED
@@ -1144,7 +1180,12 @@ _dl_map_object_from_fd (const char *name, int fd, struct filebuf *fbp,
& ~(GLRO(dl_pagesize) - 1));
c->dataend = ph->p_vaddr + ph->p_filesz;
c->allocend = ph->p_vaddr + ph->p_memsz;
c->mapoff = ph->p_offset & ~(GLRO(dl_pagesize) - 1);
if (offset & (GLRO(dl_pagesize) - 1))
{
errstring = N_("invalid offset");
goto call_lose;
}
c->mapoff = offset + ph->p_offset & ~(GLRO(dl_pagesize) - 1);
/* Determine whether there is a gap between the last segment
and this one. */
@@ -1583,6 +1624,7 @@ cannot enable executable stack as shared object requires");
/* Finally the file information. */
l->l_dev = st.st_dev;
l->l_ino = st.st_ino;
l->l_off = offset;
/* When we profile the SONAME might be needed for something else but
loading. Add it right away. */
@@ -1666,7 +1708,8 @@ print_search_path (struct r_search_path_elem **list,
this could mean there is something wrong in the installation and the
user might want to know about this. */
static int
open_verify (const char *name, struct filebuf *fbp, struct link_map *loader,
open_verify (const char *name, off_t offset,
struct filebuf *fbp, struct link_map *loader,
int whatcode, bool *found_other_class, bool free_name)
{
/* This is the expected ELF header. */
@@ -1734,6 +1777,9 @@ open_verify (const char *name, struct filebuf *fbp, struct link_map *loader,
unsigned int osversion;
size_t maplength;
if (__lseek (fd, offset, SEEK_SET) == -1)
goto close_and_out;
/* We successfully opened the file. Now verify it is a file
we can use. */
__set_errno (0);
@@ -1928,7 +1974,7 @@ open_verify (const char *name, struct filebuf *fbp, struct link_map *loader,
if MAY_FREE_DIRS is true. */
static int
open_path (const char *name, size_t namelen, int secure,
open_path (const char *name, size_t namelen, off_t offset, int secure,
struct r_search_path_struct *sps, char **realname,
struct filebuf *fbp, struct link_map *loader, int whatcode,
bool *found_other_class)
@@ -1980,8 +2026,8 @@ open_path (const char *name, size_t namelen, int secure,
if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_LIBS, 0))
_dl_debug_printf (" trying file=%s\n", buf);
fd = open_verify (buf, fbp, loader, whatcode, found_other_class,
false);
fd = open_verify (buf, offset, fbp, loader, whatcode,
found_other_class, false);
if (this_dir->status[cnt] == unknown)
{
if (fd != -1)
@@ -2075,11 +2121,42 @@ open_path (const char *name, size_t namelen, int secure,
return -1;
}
static int
match_one (const char *name, struct link_map *l)
{
/* If the requested name matches the soname of a loaded object,
use that object. Elide this check for names that have not
yet been opened. */
if (__builtin_expect (l->l_faked, 0) != 0
|| __builtin_expect (l->l_removed, 0) != 0)
return 0;
if (!_dl_name_match_p (name, l))
{
const char *soname;
if (__builtin_expect (l->l_soname_added, 1)
|| l->l_info[DT_SONAME] == NULL)
return 0;
soname = ((const char *) D_PTR (l, l_info[DT_STRTAB])
+ l->l_info[DT_SONAME]->d_un.d_val);
if (strcmp (name, soname) != 0)
return 0;
/* We have a match on a new name -- cache it. */
add_name_to_object (l, soname);
l->l_soname_added = 1;
}
/* We have a match. */
return 1;
}
/* Map in the shared object file NAME. */
struct link_map *
internal_function
_dl_map_object (struct link_map *loader, const char *name,
_dl_map_object (struct link_map *loader, const char *name, off_t offset,
int type, int trace_mode, int mode, Lmid_t nsid)
{
int fd;
@@ -2092,34 +2169,21 @@ _dl_map_object (struct link_map *loader, const char *name,
assert (nsid < GL(dl_nns));
/* Look for this name among those already loaded. */
for (l = GL(dl_ns)[nsid]._ns_loaded; l; l = l->l_next)
if (name[0] == '\0')
{
/* If the requested name matches the soname of a loaded object,
use that object. Elide this check for names that have not
yet been opened. */
if (__builtin_expect (l->l_faked, 0) != 0
|| __builtin_expect (l->l_removed, 0) != 0)
continue;
if (!_dl_name_match_p (name, l))
{
const char *soname;
/* Special case: both main exe and vdso can have empty name;
so search from head: it is important to return the map for main
a.out; else dlsym(0, ...) will fail unexpectedly. */
if (__builtin_expect (l->l_soname_added, 1)
|| l->l_info[DT_SONAME] == NULL)
continue;
soname = ((const char *) D_PTR (l, l_info[DT_STRTAB])
+ l->l_info[DT_SONAME]->d_un.d_val);
if (strcmp (name, soname) != 0)
continue;
/* We have a match on a new name -- cache it. */
add_name_to_object (l, soname);
l->l_soname_added = 1;
}
/* We have a match. */
return l;
for (l = GL(dl_ns)[nsid]._ns_loaded; l; l = l->l_next)
if (match_one (name, l))
return l;
}
else
{
for (l = _dl_last_entry (&GL(dl_ns)[nsid]); l; l = l->l_prev)
if (match_one (name, l))
return l;
}
/* Display information if we are debugging. */
@@ -2184,7 +2248,7 @@ _dl_map_object (struct link_map *loader, const char *name,
for (l = loader; l; l = l->l_loader)
if (cache_rpath (l, &l->l_rpath_dirs, DT_RPATH, "RPATH"))
{
fd = open_path (name, namelen, mode & __RTLD_SECURE,
fd = open_path (name, namelen, offset, mode & __RTLD_SECURE,
&l->l_rpath_dirs,
&realname, &fb, loader, LA_SER_RUNPATH,
&found_other_class);
@@ -2200,7 +2264,7 @@ _dl_map_object (struct link_map *loader, const char *name,
&& main_map != NULL && main_map->l_type != lt_loaded
&& cache_rpath (main_map, &main_map->l_rpath_dirs, DT_RPATH,
"RPATH"))
fd = open_path (name, namelen, mode & __RTLD_SECURE,
fd = open_path (name, namelen, offset, mode & __RTLD_SECURE,
&main_map->l_rpath_dirs,
&realname, &fb, loader ?: main_map, LA_SER_RUNPATH,
&found_other_class);
@@ -2208,7 +2272,8 @@ _dl_map_object (struct link_map *loader, const char *name,
/* Try the LD_LIBRARY_PATH environment variable. */
if (fd == -1 && env_path_list.dirs != (void *) -1)
fd = open_path (name, namelen, mode & __RTLD_SECURE, &env_path_list,
fd = open_path (name, namelen, offset,
mode & __RTLD_SECURE, &env_path_list,
&realname, &fb,
loader ?: GL(dl_ns)[LM_ID_BASE]._ns_loaded,
LA_SER_LIBPATH, &found_other_class);
@@ -2217,7 +2282,7 @@ _dl_map_object (struct link_map *loader, const char *name,
if (fd == -1 && loader != NULL
&& cache_rpath (loader, &loader->l_runpath_dirs,
DT_RUNPATH, "RUNPATH"))
fd = open_path (name, namelen, mode & __RTLD_SECURE,
fd = open_path (name, namelen, offset, mode & __RTLD_SECURE,
&loader->l_runpath_dirs, &realname, &fb, loader,
LA_SER_RUNPATH, &found_other_class);
@@ -2229,7 +2294,7 @@ _dl_map_object (struct link_map *loader, const char *name,
{
/* Check the list of libraries in the file /etc/ld.so.cache,
for compatibility with Linux's ldconfig program. */
const char *cached = _dl_load_cache_lookup (name);
const char *cached = _dl_load_cache_lookup (name, mode);
if (cached != NULL)
{
@@ -2265,7 +2330,7 @@ _dl_map_object (struct link_map *loader, const char *name,
if (cached != NULL)
{
fd = open_verify (cached,
fd = open_verify (cached, 0,
&fb, loader ?: GL(dl_ns)[nsid]._ns_loaded,
LA_SER_CONFIG, &found_other_class, false);
if (__builtin_expect (fd != -1, 1))
@@ -2287,7 +2352,8 @@ _dl_map_object (struct link_map *loader, const char *name,
&& ((l = loader ?: GL(dl_ns)[nsid]._ns_loaded) == NULL
|| __builtin_expect (!(l->l_flags_1 & DF_1_NODEFLIB), 1))
&& rtld_search_dirs.dirs != (void *) -1)
fd = open_path (name, namelen, mode & __RTLD_SECURE, &rtld_search_dirs,
fd = open_path (name, namelen, offset, mode & __RTLD_SECURE,
&rtld_search_dirs,
&realname, &fb, l, LA_SER_DEFAULT, &found_other_class);
/* Add another newline when we are tracing the library loading. */
@@ -2304,7 +2370,7 @@ _dl_map_object (struct link_map *loader, const char *name,
fd = -1;
else
{
fd = open_verify (realname, &fb,
fd = open_verify (realname, offset, &fb,
loader ?: GL(dl_ns)[nsid]._ns_loaded, 0,
&found_other_class, true);
if (__builtin_expect (fd, 0) == -1)
@@ -2366,8 +2432,8 @@ _dl_map_object (struct link_map *loader, const char *name,
}
void *stack_end = __libc_stack_end;
return _dl_map_object_from_fd (name, fd, &fb, realname, loader, type, mode,
&stack_end, nsid);
return _dl_map_object_from_fd (name, fd, offset, &fb, realname, loader, type,
mode, &stack_end, nsid);
}
+475
View File
@@ -33,6 +33,11 @@
#define VERSTAG(tag) (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGIDX (tag))
#ifndef ADDRIDX
# define ADDRIDX(tag) (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGNUM \
+ DT_EXTRANUM + DT_VALNUM + DT_ADDRTAGIDX (tag))
#endif
/* We need this string more than once. */
static const char undefined_msg[] = "undefined symbol: ";
@@ -68,6 +73,450 @@ struct sym_val
# define bump_num_relocations() ((void) 0)
#endif
/* Bob Jenkins's hash function, free for any use.
http://burtleburtle.net/bob/hash/ */
#define mix(a,b,c) \
{ \
a -= b; a -= c; a ^= (c>>13); \
b -= c; b -= a; b ^= (a<<8); \
c -= a; c -= b; c ^= (b>>13); \
a -= b; a -= c; a ^= (c>>12); \
b -= c; b -= a; b ^= (a<<16); \
c -= a; c -= b; c ^= (b>>5); \
a -= b; a -= c; a ^= (c>>3); \
b -= c; b -= a; b ^= (a<<10); \
c -= a; c -= b; c ^= (b>>15); \
}
typedef unsigned int uint32 __attribute__ ((mode (SI)));
static uint32
hash_with_seed (const char *k, uint32 length, uint32 seed)
{
uint32 a, b, c, len;
/* Set up the internal state */
len = length;
a = b = 0x9e3779b9; /* the golden ratio; an arbitrary value */
c = seed; /* the previous hash value */
/*---------------------------------------- handle most of the key */
while (len >= 12)
{
a += (k[0] +((uint32)k[1]<<8) +((uint32)k[2]<<16) +((uint32)k[3]<<24));
b += (k[4] +((uint32)k[5]<<8) +((uint32)k[6]<<16) +((uint32)k[7]<<24));
c += (k[8] +((uint32)k[9]<<8) +((uint32)k[10]<<16)+((uint32)k[11]<<24));
mix (a,b,c);
k += 12;
len -= 12;
}
/*------------------------------------- handle the last 11 bytes */
c += length;
switch (len) /* all the case statements fall through */
{
case 11: c+=((uint32)k[10]<<24);
case 10: c+=((uint32)k[9]<<16);
case 9 : c+=((uint32)k[8]<<8);
/* the first byte of c is reserved for the length */
case 8 : b+=((uint32)k[7]<<24);
case 7 : b+=((uint32)k[6]<<16);
case 6 : b+=((uint32)k[5]<<8);
case 5 : b+=k[4];
case 4 : a+=((uint32)k[3]<<24);
case 3 : a+=((uint32)k[2]<<16);
case 2 : a+=((uint32)k[1]<<8);
case 1 : a+=k[0];
/* case 0: nothing left to add */
}
mix (a,b,c);
/*-------------------------------------------- report the result */
return c;
}
/* A hash table used to speed up lookups when we have a lot of shared
libraries. We record in the table how many ELF objects in the link
map we can safely skip, because they are known to not contain the symbol
we are looking for.
Values start out at N (num objects in the main_map). We then go through
each object (executable or DSO) in their order in the main_map and insert
pos_in_map_map into the table.
If there is already an earlier (smaller) entry in the table, we leave it
alone. It could be a hash collision, or it could be an earlier
instance of the same symbol (eg weak __stdout definition in
multiple objects).
To save space, the table contains uint16_t entries, and so we can't
record main map positions over 65535.
It turns out that even when only 25% of slots are used, collision
rate is around 10%, which is quite high, and causes lookups to be slow.
So we use a second table (using a different hash seed). Hash collisions
using two separate hashes are quite rare.
Note that we allocate the two tables together (a single block twice
the size of one table). */
static void
insert_into_hash_table_1 (int pos_in_main_map, const char *symbol_name,
size_t name_len, dl_position_table_entry_t *table,
int seed)
{
uint32 hash = hash_with_seed (symbol_name, name_len, seed);
int pos = hash & GLRO(dl_position_hash_mask);
if (pos_in_main_map < table[pos])
{
table[pos] = pos_in_main_map;
if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_FASTLOAD, 0))
_dl_debug_printf ("fastload hash for %s: [%u] = %u (table %u)\n",
symbol_name, (unsigned int) pos,
(unsigned int) table[pos],
(GLRO(dl_position_hash_table) == table) ? 0 : 1);
}
else
{
if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_FASTLOAD, 0))
_dl_debug_printf
("fastload hash for %s: [%u] already set to %u <= %u (table %u)\n",
symbol_name, (unsigned int) pos,
(unsigned int) table[pos],
(unsigned int) pos_in_main_map,
(GLRO(dl_position_hash_table) == table) ? 0 : 1);
}
}
#define HASH_SEED_A 0
#define HASH_SEED_B 5381 /* As good as any other value. */
static void
insert_into_hash_table (int pos_in_main_map, const char *symbol_name)
{
dl_position_table_entry_t *const table1 = GLRO(dl_position_hash_table);
const int table_size = GLRO(dl_position_hash_mask) + 1;
dl_position_table_entry_t *const table2 = table1 + table_size;
const size_t name_len = strlen (symbol_name);
insert_into_hash_table_1 (pos_in_main_map, symbol_name, name_len, table1,
HASH_SEED_A);
insert_into_hash_table_1 (pos_in_main_map, symbol_name, name_len, table2,
HASH_SEED_B);
}
static inline int
earliest_pos_from_hash_table_1 (const char *symbol_name,
const dl_position_table_entry_t *table,
int seed)
{
int pos;
uint32 hash;
hash = hash_with_seed (symbol_name, strlen (symbol_name), seed);
pos = hash & GLRO(dl_position_hash_mask);
if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_FASTLOAD, 0))
_dl_debug_printf
("fastload earliest pos for %s: [%u] = %u (table %u)\n",
symbol_name, (unsigned int) pos, (unsigned int) table[pos],
(GLRO(dl_position_hash_table) == table) ? 0 : 1);
return table[pos];
}
static inline int
earliest_pos_from_hash_table (const char *undef_name)
{
dl_position_table_entry_t *const table1 = GLRO(dl_position_hash_table);
if (table1 == NULL)
return 0; /* Search from the beginning of the list. */
else
{
const int table_size = GLRO(dl_position_hash_mask) + 1;
dl_position_table_entry_t *const table2 = table1 + table_size;
const int skip_1 = earliest_pos_from_hash_table_1 (undef_name, table1,
HASH_SEED_A);
const int skip_2 = earliest_pos_from_hash_table_1 (undef_name, table2,
HASH_SEED_B);
/* Possibilities:
* Both skip_1 and skip_2 are positive and same:
there were no collisions at insertion in either table, or there
was double-collision with symbols from the same library.
If skip_1 == skip_2 == N (num_directly_loaded_objects), then the
slot was empty in both tables after they were filled (i.e. there
is no symbol that hashes to corresponding slot). In that case,
searching first [0, N) is pointless. See b/5609692.
True skip_to == skip_1 == skip_2.
* Both skip_1 and skip_2 are positive but different:
there was a collision in one or both tables, or one of the slots
remained unfilled after all symbols have been inserted.
It is safe to start at max, true skip_to count can not be less
than max. */
return (skip_1 < skip_2) ? skip_2 : skip_1;
}
}
static void
fill_hash_table (const struct link_map *const map, int pos_in_main_map,
int num_symbols)
{
const ElfW(Sym) *const symtab = (const void *) D_PTR (map, l_info[DT_SYMTAB]);
const char *const strtab = (const void *) D_PTR (map, l_info[DT_STRTAB]);
int k;
/* Iterate through the symbols defined in this map and insert them
into the bloom filter. If the symbol wouldn't pass the tests in
do_lookup_x(), then don't insert it. */
for (k = 0; k < num_symbols; k++)
{
const ElfW(Sym) *sym = &symtab[k];
if (sym->st_value == 0
&& ELFW(ST_TYPE) (sym->st_info) != STT_TLS)
continue;
switch (ELFW(ST_TYPE) (sym->st_info))
{
case STT_SECTION:
case STT_FILE:
case STT_COMMON:
continue;
default:
break;
}
switch (ELFW(ST_BIND) (sym->st_info))
{
case STB_LOCAL: /* Local symbols are ignored. */
continue;
default:
break;
}
insert_into_hash_table (pos_in_main_map, strtab + sym->st_name);
}
}
static dl_position_table_entry_t *
allocate_position_hash_table (size_t table_size, int max_pos)
{
/* Implementation detail: we actually allocate two "logical" tables in a
single block. */
const size_t total_size = 2 * table_size;
dl_position_table_entry_t *table
= malloc (total_size * sizeof (dl_position_table_entry_t));
if (table == NULL)
return NULL;
for (int k = 0; k < total_size; ++k)
table[k] = max_pos;
return table;
}
static int
num_dynsyms (const struct link_map *const map)
{
if (map->l_info[DT_HASH] != NULL)
{
/* If DT_HASH is present, we unconditionally use it, since it already
has the answer precomputed and waiting for us. */
const Elf_Symndx *const hash = (void *) D_PTR (map, l_info[DT_HASH]);
if (hash != NULL)
{
/* DT_HASH dynamic structure points to a symbol hash table
with the following layout:
nbucket
nchain (== number of symbols in dynamic symbol table)
bucket[0]
...
http://refspecs.freestandards.org/elf/TIS1.1.pdf (p. 2.19). */
return hash[1];
}
}
else if (map->l_info[ADDRIDX (DT_GNU_HASH)] != NULL)
{
/* The best documentation for GNU_HASH I found:
http://blogs.sun.com/ali/entry/gnu_hash_elf_sections
_dl_setup_hash() has already set things up for us. */
if (__builtin_expect (map->l_nbuckets < 1, 0))
{
/* Paranoia: neither gold nor gnu-ld will construct an empty
.gnu.hash, but some other linker just might. */
return 0;
}
/* In the GNU hash the symbol index of a symbol is determined by
the offset of the symbol's entry in the hash table itself.
We start at the last bucket map->l_gnu_chain_zero[map->l_nbuckets-1]
and loop backward from the end until we find a bucket which is
not zero.
Then we walk forward to find the last entry in the chain which
starts at that bucket. The terminating entry gives us desired
symbol index. */
int last_bucket_idx = map->l_nbuckets - 1;
while (last_bucket_idx > 0 &&
map->l_gnu_buckets[last_bucket_idx] == 0)
{
--last_bucket_idx;
}
const Elf32_Word last_bucket = map->l_gnu_buckets[last_bucket_idx];
if (__builtin_expect (last_bucket == 0, 0))
{
/* This shouldn't happen unless the library has only static
variables with global ctors, and nothing else. */
return 0;
}
/* Start of the hash chain for the last non-zero bucket. */
const Elf32_Word *hasharr = &map->l_gnu_chain_zero[last_bucket];
/* The chain is terminated by an entry with LSBit set. */
while ((*hasharr & 1u) == 0)
++hasharr;
/* Size of dynamic symbol table is "index of last symbol" + 1. */
return hasharr - map->l_gnu_chain_zero + 1;
}
return 0;
}
/* Create the fastload position hash (if requested). Given a link_map
containing all required objects, iterate through all symbols. For each
symbol which could match in do_lookup_x, insert the index of the
providing object in main_map. */
void
internal_function
_dl_fill_position_hash (struct link_map *main_map)
{
const int num_objects = main_map->l_searchlist.r_nlist;
const int debug_fastload = GLRO(dl_debug_mask) & DL_DEBUG_FASTLOAD;
int k;
/* If we have more than dl_position_hash_cutoff shared libraries,
fill in the hash table of earliest known positions for symbols in
main_map. We'll use this in do_lookup_x(). */
/* If cutoff or size is negative, fastload is disabled. */
if (GLRO(dl_position_hash_cutoff) < 0 || GLRO(dl_position_hash_bits) < 0)
{
if (__builtin_expect (debug_fastload, 0))
_dl_debug_printf ("fastload: disabled (configuration)\n");
return;
}
/* If we don't have enough mapped objects, fastload is disabled. */
if (num_objects <= GLRO(dl_position_hash_cutoff))
{
if (__builtin_expect (debug_fastload, 0))
_dl_debug_printf ("fastload: disabled (too few objects,"
" %u <= cutoff %u)\n",
num_objects, GLRO(dl_position_hash_cutoff));
return;
}
int *ndynsyms = NULL;
if (GLRO(dl_position_hash_bits) == 0)
{
/* Table size has not been specified via LD_FASTLOAD_HASH_BITS.
Compute appropriate size for <= 25% load factor. */
int total_symbols = 0;
/* It is safe to call alloca() here, because we are executing in
the context of dl_main, i.e. we are on the main stack, and are
not yet using much of it. Assuming sane upper limit of 10K direct
dependencies, we'll use at most 40K bytes here. */
ndynsyms = alloca (num_objects * sizeof (int));
for (k = 0; k < num_objects; ++k)
{
const struct link_map *const map = main_map->l_searchlist.r_list[k];
const int nsyms = num_dynsyms (map);
ndynsyms[k] = nsyms;
total_symbols += nsyms;
if (__builtin_expect (debug_fastload, 0))
_dl_debug_printf ("fastload: %s: %u symbols\n", map->l_name, nsyms);
}
/* Ensure table size is >= 4 * total_symbols. Generally this
over-sizes the table by more than 4, since there usually are lots
of duplicate symbols (from different DSOs) as well. */
GLRO(dl_position_hash_bits)
= (8 * sizeof (total_symbols)) - __builtin_clz (total_symbols) + 2;
if (__builtin_expect (debug_fastload, 0))
_dl_debug_printf ("fastload: will use %u hash bits for %u total "
"symbols\n",
GLRO(dl_position_hash_bits), total_symbols);
}
/* If the requested or computed table size is too large, limit it. */
if (GLRO(dl_position_hash_bits) > DL_POSITION_HASH_BITS_MAX)
{
if (__builtin_expect (debug_fastload, 0))
_dl_debug_printf ("fastload: requested table too large"
" (%u > max %u bits)\n",
GLRO(dl_position_hash_bits),
DL_POSITION_HASH_BITS_MAX);
GLRO(dl_position_hash_bits) = DL_POSITION_HASH_BITS_MAX;
}
int table_size = 1 << GLRO(dl_position_hash_bits);
GLRO(dl_position_hash_mask) = table_size - 1;
if (__builtin_expect (debug_fastload, 0))
_dl_debug_printf ("fastload: enabled with %u entry table\n", table_size);
int max_pos = num_objects < DL_POSITION_MAX ? num_objects : DL_POSITION_MAX;
GLRO(dl_position_hash_table) = allocate_position_hash_table (table_size,
max_pos);
if (GLRO(dl_position_hash_table) == NULL)
{
if (__builtin_expect (debug_fastload, 0))
_dl_debug_printf ("fastload: failed to allocate table\n");
return;
}
/* There is no point in going beyond max_pos: the rest of the table
has already been saturated with max_pos value. */
for (k = 0; k < max_pos; ++k)
{
const struct link_map *const map = main_map->l_searchlist.r_list[k];
/* Reuse num_dynsyms() result we computed earlier if possible:
recomputing it may be somewhat expensive with DT_GNU_HASH. */
const int nsyms = ndynsyms ? ndynsyms[k] : num_dynsyms (map);
fill_hash_table (map, k, nsyms);
}
}
/* Inner part of the lookup functions. We return a value > 0 if we
found the symbol, the value 0 if nothing is found and < 0 if
@@ -88,6 +537,32 @@ do_lookup_x (const char *undef_name, uint_fast32_t new_hash,
__asm volatile ("" : "+r" (n), "+m" (scope->r_list));
struct link_map **list = scope->r_list;
if (scope == GL(dl_ns)[LM_ID_BASE]._ns_main_searchlist && i == 0)
{
const int skip_to = earliest_pos_from_hash_table (undef_name);
if (skip_to < n)
{
i = skip_to;
if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_FASTLOAD, 0))
_dl_debug_printf ("fastload %s skipping to %u\n",
undef_name, (unsigned int) i);
}
else
{
/* Symbol was not found in any of the initial libraries,
and no new libraries have been added. */
assert (skip_to == n);
if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_FASTLOAD, 0))
_dl_debug_printf ("fastload %s, %u >= %u (scope->r_nlist)\n",
undef_name, (unsigned int) skip_to,
(unsigned int) n);
return 0;
}
}
do
{
/* These variables are used in the nested function. */
+142
View File
@@ -19,6 +19,7 @@
#include <assert.h>
#include <fcntl.h>
#include <ldsodefs.h>
#include <libc-symbols.h>
#include <limits.h>
#include <link.h>
#include <stdarg.h>
@@ -364,3 +365,144 @@ _dl_higher_prime_number (unsigned long int n)
return *low;
}
/* To support accessing TLS variables from signal handlers, we need an
async signal safe memory allocator. These routines are never
themselves invoked reentrantly (all calls to them are surrounded by
signal masks) but may be invoked concurrently from many threads.
The current implementation is not particularly performant nor space
efficient, but it will be used rarely (and only in binaries that use
dlopen.) The API matches that of malloc() and friends. */
struct __signal_safe_allocator_header
{
size_t size;
void *start;
};
static inline struct __signal_safe_allocator_header *
ptr_to_signal_safe_allocator_header (void *ptr)
{
return (struct __signal_safe_allocator_header *)
((char *) (ptr) - sizeof (struct __signal_safe_allocator_header));
}
void *weak_function
__signal_safe_memalign (size_t boundary, size_t size)
{
struct __signal_safe_allocator_header *header;
if (boundary < sizeof (*header))
boundary = sizeof (*header);
/* Boundary must be a power of two. */
if (!powerof2 (boundary))
return NULL;
size_t pg = GLRO (dl_pagesize);
size_t padded_size;
if (boundary <= pg)
{
/* We'll get a pointer certainly aligned to boundary, so just
add one more boundary-sized chunk to hold the header. */
padded_size = roundup (size, boundary) + boundary;
}
else
{
/* If we want K pages aligned to a J-page boundary, K+J+1 pages
contains at least one such region that isn't directly at the start
(so we can place the header.) This is wasteful, but you're the one
who wanted 64K-aligned TLS. */
padded_size = roundup (size, pg) + boundary + pg;
}
size_t actual_size = roundup (padded_size, pg);
void *actual = mmap (NULL, actual_size, PROT_READ | PROT_WRITE,
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
if (actual == MAP_FAILED)
return NULL;
if (boundary <= pg)
{
header = actual + boundary - sizeof (*header);
}
else
{
intptr_t actual_pg = ((intptr_t) actual) / pg;
intptr_t boundary_pg = boundary / pg;
intptr_t start_pg = actual_pg + boundary_pg;
start_pg -= start_pg % boundary_pg;
if (start_pg > (actual_pg + 1))
{
int ret = munmap (actual, (start_pg - actual_pg - 1) * pg);
assert (ret == 0);
actual = (void *) ((start_pg - 1) * pg);
}
char *start = (void *) (start_pg * pg);
header = ptr_to_signal_safe_allocator_header (start);
}
header->size = actual_size;
header->start = actual;
void *ptr = header;
ptr += sizeof (*header);
if (((intptr_t) ptr) % boundary != 0)
_dl_fatal_printf ("__signal_safe_memalign produced incorrect alignment\n");
return ptr;
}
void * weak_function
__signal_safe_malloc (size_t size)
{
return __signal_safe_memalign (1, size);
}
void weak_function
__signal_safe_free (void *ptr)
{
if (ptr == NULL)
return;
struct __signal_safe_allocator_header *header
= ptr_to_signal_safe_allocator_header (ptr);
int ret = munmap (header->start, header->size);
assert (ret == 0);
}
void * weak_function
__signal_safe_realloc (void *ptr, size_t size)
{
if (size == 0)
{
__signal_safe_free (ptr);
return NULL;
}
if (ptr == NULL)
return __signal_safe_malloc (size);
struct __signal_safe_allocator_header *header
= ptr_to_signal_safe_allocator_header (ptr);
size_t old_size = header->size;
if (old_size - sizeof (*header) >= size)
return ptr;
void *new_ptr = __signal_safe_malloc (size);
if (new_ptr == NULL)
return NULL;
memcpy (new_ptr, ptr, old_size);
__signal_safe_free (ptr);
return new_ptr;
}
void * weak_function
__signal_safe_calloc (size_t nmemb, size_t size)
{
void *ptr = __signal_safe_malloc (nmemb * size);
if (ptr == NULL)
return NULL;
return memset (ptr, 0, nmemb * size);
}
+10 -4
View File
@@ -45,6 +45,8 @@ extern int __libc_multiple_libcs; /* Defined in init-first.c. */
struct dl_open_args
{
const char *file;
/* ELF header at offset in file. */
off_t offset;
int mode;
/* This is the caller of the dlopen() function. */
const void *caller_dlopen;
@@ -221,7 +223,7 @@ dl_open_worker (void *a)
/* Load the named object. */
struct link_map *new;
args->map = new = _dl_map_object (call_map, file, lt_loaded, 0,
args->map = new = _dl_map_object (call_map, file, args->offset, lt_loaded, 0,
mode | __RTLD_CALLMAP, args->nsid);
/* If the pointer returned is NULL this means the RTLD_NOLOAD flag is
@@ -548,7 +550,10 @@ cannot load any more object with static TLS"));
generation of the DSO we are allocating data for. */
_dl_update_slotinfo (imap->l_tls_modid);
#endif
/* We do this iteration under a signal mask in dl-reloc; why not
here? Because these symbols are new and dlopen hasn't
returned yet. So we can't possibly be racing with a TLS
access to them from another thread. */
GL(dl_init_static_tls) (imap);
assert (imap->l_need_tls_init == 0);
}
@@ -589,9 +594,9 @@ cannot load any more object with static TLS"));
new->l_name, new->l_ns, new->l_direct_opencount);
}
void *
_dl_open (const char *file, int mode, const void *caller_dlopen, Lmid_t nsid,
_dl_open (const char *file, off_t offset, int mode,
const void *caller_dlopen, Lmid_t nsid,
int argc, char *argv[], char *env[])
{
if ((mode & RTLD_BINDING_MASK) == 0)
@@ -635,6 +640,7 @@ no more namespaces available for dlmopen()"));
struct dl_open_args args;
args.file = file;
args.offset = offset;
args.mode = mode;
args.caller_dlopen = caller_dlopen;
args.caller_dl_open = RETURN_ADDRESS (0);
+43 -5
View File
@@ -16,8 +16,10 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <atomic.h>
#include <errno.h>
#include <libintl.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#include <ldsodefs.h>
@@ -70,8 +72,6 @@ _dl_try_allocate_static_tls (struct link_map *map)
size_t offset = GL(dl_tls_static_used) + (freebytes - n * map->l_tls_align
- map->l_tls_firstbyte_offset);
map->l_tls_offset = GL(dl_tls_static_used) = offset;
#elif TLS_DTV_AT_TP
/* dl_tls_static_used includes the TCB at the beginning. */
size_t offset = (((GL(dl_tls_static_used)
@@ -83,7 +83,36 @@ _dl_try_allocate_static_tls (struct link_map *map)
if (used > GL(dl_tls_static_size))
goto fail;
map->l_tls_offset = offset;
#else
# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
#endif
/* We've computed the new value we want, now try to install it. */
ptrdiff_t val;
if ((val = map->l_tls_offset) == NO_TLS_OFFSET)
{
/* l_tls_offset starts out at NO_TLS_OFFSET, and all attempts to
change it go from NO_TLS_OFFSET to some other value. We use
compare_and_exchange to ensure only one attempt succeeds. We
don't actually need any memory ordering here, but _acq is the
weakest available. */
(void ) atomic_compare_and_exchange_bool_acq (&map->l_tls_offset,
offset,
NO_TLS_OFFSET);
val = map->l_tls_offset;
assert (val != NO_TLS_OFFSET);
}
if (val != offset)
{
/* We'd like to set a static offset for this section, but another
thread has already used a dynamic TLS block for it. Since we can
only use static offsets if everyone does (and it's not practical
to move that thread's dynamic block), we have to fail. */
goto fail;
}
/* We installed the value; now update the globals. */
#if TLS_TCB_AT_TP
GL(dl_tls_static_used) = offset;
#elif TLS_DTV_AT_TP
map->l_tls_firstbyte_offset = GL(dl_tls_static_used);
GL(dl_tls_static_used) = used;
#else
@@ -114,8 +143,17 @@ void
internal_function __attribute_noinline__
_dl_allocate_static_tls (struct link_map *map)
{
if (map->l_tls_offset == FORCED_DYNAMIC_TLS_OFFSET
|| _dl_try_allocate_static_tls (map))
/* We wrap this in a signal mask because it has to iterate all threads
(including this one) and update this map's TLS entry. A signal handler
accessing TLS would try to do the same update and break. */
sigset_t old;
_dl_mask_all_signals (&old);
int err = -1;
if (map->l_tls_offset != FORCED_DYNAMIC_TLS_OFFSET)
err = _dl_try_allocate_static_tls (map);
_dl_unmask_signals (&old);
if (err != 0)
{
_dl_signal_error (0, map->l_name, NULL, N_("\
cannot allocate memory in static TLS block"));
+14
View File
@@ -67,6 +67,9 @@ void *__libc_stack_end;
/* Path where the binary is found. */
const char *_dl_origin_path;
/* Directory where the AT_EXECFN is found. */
const char *_google_exec_origin_dir;
/* Nonzero if runtime lookup should not update the .got/.plt. */
int _dl_bind_not;
@@ -142,6 +145,12 @@ hp_timing_t _dl_cpuclock_offset;
void (*_dl_init_static_tls) (struct link_map *) = &_dl_nothread_init_static_tls;
/* The merged position hash table used if we have a lot of shared objects. */
dl_position_table_entry_t *_dl_position_hash_table;
int _dl_position_hash_mask;
int _dl_position_hash_cutoff = DL_POSITION_HASH_CUTOFF_DEFAULT;
int _dl_position_hash_bits;
size_t _dl_pagesize = EXEC_PAGESIZE;
int _dl_inhibit_cache;
@@ -222,6 +231,8 @@ __rtld_lock_define_initialized_recursive (, _dl_load_lock)
that list. */
__rtld_lock_define_initialized_recursive (, _dl_load_write_lock)
/* Colon-separated list of absolute paths to ld.so.cache files we'll load. */
const char *_google_ld_so_cache_list = GOOGLE_LD_SO_CACHE_LIST;
#ifdef HAVE_AUX_VECTOR
int _dl_clktck;
@@ -234,6 +245,9 @@ _dl_aux_init (ElfW(auxv_t) *av)
uid_t uid = 0;
gid_t gid = 0;
extern ElfW(auxv_t) *__google_auxv;
__google_auxv = av;
_dl_auxv = av;
for (; av->a_type != AT_NULL; ++av)
switch (av->a_type)
+105 -52
View File
@@ -17,6 +17,7 @@
<http://www.gnu.org/licenses/>. */
#include <assert.h>
#include <atomic.h>
#include <errno.h>
#include <libintl.h>
#include <signal.h>
@@ -293,7 +294,7 @@ allocate_dtv (void *result)
initial set of modules. This should avoid in most cases expansions
of the dtv. */
dtv_length = GL(dl_tls_max_dtv_idx) + DTV_SURPLUS;
dtv = calloc (dtv_length + 2, sizeof (dtv_t));
dtv = __signal_safe_calloc (dtv_length + 2, sizeof (dtv_t));
if (dtv != NULL)
{
/* This is the initial length of the dtv. */
@@ -463,6 +464,18 @@ _dl_allocate_tls (void *mem)
}
rtld_hidden_def (_dl_allocate_tls)
void
internal_function
_dl_clear_dtv (dtv_t *dtv)
{
for (size_t cnt = 0; cnt < dtv[-1].counter; ++cnt)
if (! dtv[1 + cnt].pointer.is_static
&& dtv[1 + cnt].pointer.val != TLS_DTV_UNALLOCATED)
__signal_safe_free (dtv[1 + cnt].pointer.val);
memset (dtv, '\0', (dtv[-1].counter + 1) * sizeof (dtv_t));
}
rtld_hidden_def (_dl_clear_dtv)
#ifndef SHARED
extern dtv_t _dl_static_dtv[];
@@ -479,11 +492,11 @@ _dl_deallocate_tls (void *tcb, bool dealloc_tcb)
for (size_t cnt = 0; cnt < dtv[-1].counter; ++cnt)
if (! dtv[1 + cnt].pointer.is_static
&& dtv[1 + cnt].pointer.val != TLS_DTV_UNALLOCATED)
free (dtv[1 + cnt].pointer.val);
__signal_safe_free (dtv[1 + cnt].pointer.val);
/* The array starts with dtv[-1]. */
if (dtv != GL(dl_initial_dtv))
free (dtv - 1);
__signal_safe_free (dtv - 1);
if (dealloc_tcb)
{
@@ -521,20 +534,21 @@ rtld_hidden_def (_dl_deallocate_tls)
# endif
static void *
allocate_and_init (struct link_map *map)
static void
allocate_and_init (dtv_t *dtv, struct link_map *map)
{
void *newp;
newp = __libc_memalign (map->l_tls_align, map->l_tls_blocksize);
newp = __signal_safe_memalign (map->l_tls_align, map->l_tls_blocksize);
if (newp == NULL)
oom ();
/* Initialize the memory. */
/* Initialize the memory. Since this is our thread's space, we are
under a signal mask, and no one has touched this section before,
we can safely just overwrite whatever's there. */
memset (__mempcpy (newp, map->l_tls_initimage, map->l_tls_initimage_size),
'\0', map->l_tls_blocksize - map->l_tls_initimage_size);
return newp;
dtv->pointer.val = newp;
}
@@ -576,7 +590,15 @@ _dl_update_slotinfo (unsigned long int req_modid)
the entry we need. */
size_t new_gen = listp->slotinfo[idx].gen;
size_t total = 0;
sigset_t old;
_dl_mask_all_signals (&old);
/* We use the signal mask as a lock against reentrancy here.
Check that a signal taken before the lock didn't already
update us. */
dtv = THREAD_DTV ();
if (dtv[0].counter >= listp->slotinfo[idx].gen)
goto out;
/* We have to look through the entire dtv slotinfo list. */
listp = GL(dl_tls_dtv_slotinfo_list);
do
@@ -596,25 +618,27 @@ _dl_update_slotinfo (unsigned long int req_modid)
if (gen <= dtv[0].counter)
continue;
size_t modid = total + cnt;
/* If there is no map this means the entry is empty. */
struct link_map *map = listp->slotinfo[cnt].map;
if (map == NULL)
{
/* If this modid was used at some point the memory
might still be allocated. */
if (! dtv[total + cnt].pointer.is_static
&& dtv[total + cnt].pointer.val != TLS_DTV_UNALLOCATED)
if (dtv[-1].counter >= modid
&& !dtv[modid].pointer.is_static
&& dtv[modid].pointer.val != TLS_DTV_UNALLOCATED)
{
free (dtv[total + cnt].pointer.val);
dtv[total + cnt].pointer.val = TLS_DTV_UNALLOCATED;
__signal_safe_free (dtv[modid].pointer.val);
dtv[modid].pointer.val = TLS_DTV_UNALLOCATED;
}
continue;
}
assert (modid == map->l_tls_modid);
/* Check whether the current dtv array is large enough. */
size_t modid = map->l_tls_modid;
assert (total + cnt == modid);
if (dtv[-1].counter < modid)
{
/* Reallocate the dtv. */
@@ -628,17 +652,18 @@ _dl_update_slotinfo (unsigned long int req_modid)
{
/* This is the initial dtv that was allocated
during rtld startup using the dl-minimal.c
malloc instead of the real malloc. We can't
malloc instead of the real allocator. We can't
free it, we have to abandon the old storage. */
newp = malloc ((2 + newsize) * sizeof (dtv_t));
newp = __signal_safe_malloc (
(2 + newsize) * sizeof (dtv_t));
if (newp == NULL)
oom ();
memcpy (newp, &dtv[-1], (2 + oldsize) * sizeof (dtv_t));
}
else
{
newp = realloc (&dtv[-1],
newp = __signal_safe_realloc (&dtv[-1],
(2 + newsize) * sizeof (dtv_t));
if (newp == NULL)
oom ();
@@ -668,12 +693,17 @@ _dl_update_slotinfo (unsigned long int req_modid)
deallocate even if it is this dtv entry we are
supposed to load. The reason is that we call
memalign and not malloc. */
free (dtv[modid].pointer.val);
__signal_safe_free (dtv[modid].pointer.val);
/* This module is loaded dynamically- We defer memory
allocation. */
dtv[modid].pointer.is_static = false;
dtv[modid].pointer.val = TLS_DTV_UNALLOCATED;
/* Google-local fix for issues solved differently upstream. */
if (map->l_tls_offset == NO_TLS_OFFSET
|| map->l_tls_offset == FORCED_DYNAMIC_TLS_OFFSET)
{
/* This module is loaded dynamically- We defer memory
allocation. */
dtv[modid].pointer.is_static = false;
dtv[modid].pointer.val = TLS_DTV_UNALLOCATED;
}
if (modid == req_modid)
the_map = map;
@@ -685,6 +715,8 @@ _dl_update_slotinfo (unsigned long int req_modid)
/* This will be the new maximum generation counter. */
dtv[0].counter = new_gen;
out:
_dl_unmask_signals (&old);
}
return the_map;
@@ -710,39 +742,60 @@ tls_get_addr_tail (GET_ADDR_ARGS, dtv_t *dtv, struct link_map *the_map)
the_map = listp->slotinfo[idx].map;
}
sigset_t old;
_dl_mask_all_signals (&old);
again:
/* Make sure that, if a dlopen running in parallel forces the
variable into static storage, we'll wait until the address in the
static TLS block is set up, and use that. If we're undecided
yet, make sure we make the decision holding the lock as well. */
if (__builtin_expect (the_map->l_tls_offset
!= FORCED_DYNAMIC_TLS_OFFSET, 0))
/* As with update_slotinfo, we use the sigmask as a check against
reentrancy. */
if (dtv[GET_ADDR_MODULE].pointer.val != TLS_DTV_UNALLOCATED)
goto out;
/* Synchronize against a parallel dlopen() forcing this variable
into static storage. If that happens, we have to be more careful
about initializing the area, as that dlopen() will be iterating
the threads to do so itself. */
ptrdiff_t offset;
if ((offset = the_map->l_tls_offset) == NO_TLS_OFFSET)
{
__rtld_lock_lock_recursive (GL(dl_load_lock));
if (__builtin_expect (the_map->l_tls_offset == NO_TLS_OFFSET, 1))
{
the_map->l_tls_offset = FORCED_DYNAMIC_TLS_OFFSET;
__rtld_lock_unlock_recursive (GL(dl_load_lock));
}
else
{
__rtld_lock_unlock_recursive (GL(dl_load_lock));
if (__builtin_expect (the_map->l_tls_offset
!= FORCED_DYNAMIC_TLS_OFFSET, 1))
{
void *p = dtv[GET_ADDR_MODULE].pointer.val;
if (__builtin_expect (p == TLS_DTV_UNALLOCATED, 0))
goto again;
return (char *) p + GET_ADDR_OFFSET;
}
}
/* l_tls_offset starts out at NO_TLS_OFFSET, and all attempts to
change it go from NO_TLS_OFFSET to some other value. We use
compare_and_exchange to ensure only one attempt succeeds. We
don't actually need any memory ordering here, but _acq is the
weakest available. */
(void) atomic_compare_and_exchange_bool_acq (&the_map->l_tls_offset,
FORCED_DYNAMIC_TLS_OFFSET,
NO_TLS_OFFSET);
offset = the_map->l_tls_offset;
assert (offset != NO_TLS_OFFSET);
}
void *p = dtv[GET_ADDR_MODULE].pointer.val = allocate_and_init (the_map);
dtv[GET_ADDR_MODULE].pointer.is_static = false;
if (offset == FORCED_DYNAMIC_TLS_OFFSET)
{
allocate_and_init (&dtv[GET_ADDR_MODULE], the_map);
}
else
{
void ** volatile pp = &dtv[GET_ADDR_MODULE].pointer.val;
while (atomic_forced_read (*pp) == TLS_DTV_UNALLOCATED)
{
/* for lack of a better (safe) thing to do, just spin.
Someone else (not us; it's done under a signal mask) set
this map to a static TLS offset, and they'll iterate all
threads to initialize it. They'll eventually write
to pointer.val, at which point we know they've fully
completed initialization. */
atomic_delay ();
}
/* Make sure we've picked up their initialization of the actual
block; this pairs against the write barrier in
init_one_static_tls, guaranteeing that we see their write of
the tls_initimage into the static region. */
atomic_read_barrier ();
}
out:
assert (dtv[GET_ADDR_MODULE].pointer.val != TLS_DTV_UNALLOCATED);
_dl_unmask_signals (&old);
return (char *) p + GET_ADDR_OFFSET;
return (char *) dtv[GET_ADDR_MODULE].pointer.val + GET_ADDR_OFFSET;
}
+17 -4
View File
@@ -53,10 +53,23 @@ find_needed (const char *name, struct link_map *map)
struct link_map *tmap;
unsigned int n;
for (tmap = GL(dl_ns)[map->l_ns]._ns_loaded; tmap != NULL;
tmap = tmap->l_next)
if (_dl_name_match_p (name, tmap))
return tmap;
if (name[0] == '\0')
{
/* Special case: both main exe and vdso can have empty name;
so search from head: it is important to return the map for main
a.out; else dlsym(0, ...) will fail unexpectedly. */
for (tmap = GL(dl_ns)[map->l_ns]._ns_loaded; tmap != NULL;
tmap = tmap->l_next)
if (_dl_name_match_p (name, tmap))
return tmap;
}
else
{
for (tmap = _dl_last_entry (&GL(dl_ns)[map->l_ns]); tmap != NULL;
tmap = tmap->l_prev)
if (_dl_name_match_p (name, tmap))
return tmap;
}
/* The required object is not in the global scope, look to see if it is
a dependency of the current object. */
+3
View File
@@ -2283,6 +2283,9 @@ typedef Elf32_Addr Elf32_Conflict;
#define DT_PPC64_OPD (DT_LOPROC + 1)
#define DT_PPC64_OPDSZ (DT_LOPROC + 2)
#define DT_PPC64_OPT (DT_LOPROC + 3)
/* This should have the value 4, to match with the four tag values
above, but the change needs to be coordinated with an update to
L_INFO_ELEMENTS in libunwind/google_link.h. */
#define DT_PPC64_NUM 3
/* PowerPC64 specific values for the DT_PPC64_OPT Dyn entry. */
+10 -21
View File
@@ -150,31 +150,23 @@ for file do
echo "ldd: ${file}:" $"not regular file" >&2
result=1
elif test -r "$file"; then
test -x "$file" || echo 'ldd:' $"\
warning: you do not have execution permission for" "\`$file'" >&2
RTLD=
ret=1
for rtld in ${RTLDLIST}; do
if test -x $rtld; then
verify_out=`${rtld} --verify "$file"`
ret=$?
case $ret in
[02]) RTLD=${rtld}; break;;
esac
dummy=`$rtld 2>&1`
if test $? = 127; then
verify_out=`${rtld} --verify "$file"`
ret=$?
case $ret in
[02]) RTLD=${rtld}; break;;
esac
fi
fi
done
case $ret in
0)
# If the program exits with exit code 5, it means the process has been
# invoked with __libc_enable_secure. Fall back to running it through
# the dynamic linker.
try_trace "$file"
rc=$?
if [ $rc = 5 ]; then
try_trace "$RTLD" "$file"
rc=$?
fi
[ $rc = 0 ] || result=1
0|2)
try_trace "$RTLD" "$file" || result=1
;;
1)
# This can be a non-ELF binary or no binary at all.
@@ -183,9 +175,6 @@ warning: you do not have execution permission for" "\`$file'" >&2
result=1
}
;;
2)
try_trace "$RTLD" "$file" || result=1
;;
*)
echo 'ldd:' ${RTLD} $"exited with unknown exit code" "($ret)" >&2
exit 1
+4 -4
View File
@@ -34,6 +34,8 @@
#include <bits/elfclass.h> /* Defines __ELF_NATIVE_CLASS. */
#include <bits/link.h>
__BEGIN_DECLS
/* Rendezvous structure used by the run-time dynamic linker to communicate
details of shared object loading to the debugger. If the executable's
dynamic section has a DT_DEBUG element, the run-time linker sets that
@@ -162,8 +164,6 @@ struct dl_phdr_info
void *dlpi_tls_data;
};
__BEGIN_DECLS
extern int dl_iterate_phdr (int (*__callback) (struct dl_phdr_info *,
size_t, void *),
void *__data);
@@ -187,8 +187,8 @@ extern uintptr_t la_symbind64 (Elf64_Sym *__sym, unsigned int __ndx,
unsigned int *__flags, const char *__symname);
extern unsigned int la_objclose (uintptr_t *__cookie);
__END_DECLS
#endif
__END_DECLS
#endif /* link.h */
+151 -16
View File
@@ -51,6 +51,12 @@ extern __typeof (__mempcpy) __mempcpy attribute_hidden;
extern __typeof (_exit) exit_internal asm ("_exit") attribute_hidden;
#define _exit exit_internal
/* Iterate over auxv, find AT_EXECFN if any. */
static char * get_at_execfn(ElfW(auxv_t) *auxv);
/* Given file path, return fully resolved directory path. */
static char * get_directory (const char *file_path);
/* Helper function to handle errors while resolving symbols. */
static void print_unresolved (int errcode, const char *objname,
const char *errsting);
@@ -73,6 +79,9 @@ enum mode { normal, list, verify, trace };
all the entries. */
static void process_envvars (enum mode *modep);
/* Set GLRO(google_exec_origin_dir). */
static void set_exec_origin_dir(const char *exe_path);
#ifdef DL_ARGV_NOT_RELRO
int _dl_argc attribute_hidden;
char **_dl_argv = NULL;
@@ -162,7 +171,6 @@ struct rtld_global_ro _rtld_global_ro attribute_relro =
._dl_hwcap_mask = HWCAP_IMPORTANT,
._dl_lazy = 1,
._dl_fpu_control = _FPU_DEFAULT,
._dl_pointer_guard = 1,
._dl_pagesize = EXEC_PAGESIZE,
._dl_inhibit_cache = 0,
@@ -176,6 +184,8 @@ struct rtld_global_ro _rtld_global_ro attribute_relro =
._dl_open = _dl_open,
._dl_close = _dl_close,
._dl_tls_get_addr_soft = _dl_tls_get_addr_soft,
._dl_position_hash_cutoff = DL_POSITION_HASH_CUTOFF_DEFAULT,
._dl_position_hash_bits = 0,
#ifdef HAVE_DL_DISCOVER_OSVERSION
._dl_discover_osversion = _dl_discover_osversion
#endif
@@ -623,15 +633,15 @@ static void
map_doit (void *a)
{
struct map_args *args = (struct map_args *) a;
args->map = _dl_map_object (args->loader, args->str, lt_library, 0,
args->mode, LM_ID_BASE);
args->map = _dl_map_object (args->loader, args->str, 0, lt_library,
0, args->mode, LM_ID_BASE);
}
static void
dlmopen_doit (void *a)
{
struct dlmopen_args *args = (struct dlmopen_args *) a;
args->map = _dl_open (args->fname,
args->map = _dl_open (args->fname, 0,
(RTLD_LAZY | __RTLD_DLOPEN | __RTLD_AUDIT
| __RTLD_SECURE),
dl_main, LM_ID_NEWLM, _dl_argc, INTUSE(_dl_argv),
@@ -857,15 +867,12 @@ security_init (void)
#endif
/* Set up the pointer guard as well, if necessary. */
if (GLRO(dl_pointer_guard))
{
uintptr_t pointer_chk_guard = _dl_setup_pointer_guard (_dl_random,
stack_chk_guard);
uintptr_t pointer_chk_guard
= _dl_setup_pointer_guard (_dl_random, stack_chk_guard);
#ifdef THREAD_SET_POINTER_GUARD
THREAD_SET_POINTER_GUARD (pointer_chk_guard);
THREAD_SET_POINTER_GUARD (pointer_chk_guard);
#endif
__pointer_chk_guard_local = pointer_chk_guard;
}
__pointer_chk_guard_local = pointer_chk_guard;
/* We do not need the _dl_random value anymore. The less
information we leave behind, the better, so clear the
@@ -1032,6 +1039,8 @@ of this helper program; chances are you did not intend to run this program.\n\
in LIST\n\
--audit LIST use objects named in LIST as auditors\n");
set_exec_origin_dir (INTUSE(_dl_argv)[1]);
++_dl_skip_args;
--_dl_argc;
++INTUSE(_dl_argv);
@@ -1075,7 +1084,7 @@ of this helper program; chances are you did not intend to run this program.\n\
else
{
HP_TIMING_NOW (start);
_dl_map_object (NULL, rtld_progname, lt_library, 0,
_dl_map_object (NULL, rtld_progname, 0, lt_library, 0,
__RTLD_OPENEXEC, LM_ID_BASE);
HP_TIMING_NOW (stop);
@@ -1126,6 +1135,8 @@ of this helper program; chances are you did not intend to run this program.\n\
}
else
{
set_exec_origin_dir (get_at_execfn (auxv));
/* Create a link_map for the executable itself.
This will be what dlopen on "" returns. */
main_map = _dl_new_object ((char *) "", "", lt_executable, NULL,
@@ -1636,6 +1647,10 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
HP_TIMING_ACCUM_NT (load_time, diff);
}
#if ENABLE_ETC_LD_SO_PRELOAD /* Google-local: we don't want
/etc/ld.so.preload for GRTE. */
/* There usually is no ld.so.preload file, it should only be used
for emergencies and testing. So the open call etc should usually
fail. Using access() on a non-existing file is faster than using
@@ -1720,6 +1735,8 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
}
}
#endif /* end "/etc/ld.so.preload" disable. */
if (__builtin_expect (*first_preload != NULL, 0))
{
/* Set up PRELOADS with a vector of the preloaded libraries. */
@@ -1739,6 +1756,11 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
dependencies in the executable's searchlist for symbol resolution. */
HP_TIMING_NOW (start);
_dl_map_object_deps (main_map, preloads, npreloads, mode == trace, 0);
/* We have now finished loading every required (linked-in) object.
Set up the position hash if needed. */
_dl_fill_position_hash (main_map);
HP_TIMING_NOW (stop);
HP_TIMING_DIFF (diff, start, stop);
HP_TIMING_ACCUM_NT (load_time, diff);
@@ -2367,10 +2389,12 @@ process_dl_debug (const char *dl_debug)
DL_DEBUG_VERSIONS | DL_DEBUG_IMPCALLS },
{ LEN_AND_STR ("scopes"), "display scope information",
DL_DEBUG_SCOPES },
{ LEN_AND_STR ("fastload"), "display fastload information",
DL_DEBUG_FASTLOAD },
{ LEN_AND_STR ("all"), "all previous options combined",
DL_DEBUG_LIBS | DL_DEBUG_RELOC | DL_DEBUG_FILES | DL_DEBUG_SYMBOLS
| DL_DEBUG_BINDINGS | DL_DEBUG_VERSIONS | DL_DEBUG_IMPCALLS
| DL_DEBUG_SCOPES },
| DL_DEBUG_SCOPES | DL_DEBUG_FASTLOAD },
{ LEN_AND_STR ("statistics"), "display relocation statistics",
DL_DEBUG_STATISTICS },
{ LEN_AND_STR ("unused"), "determined unused DSOs",
@@ -2488,6 +2512,8 @@ process_envvars (enum mode *modep)
GLRO(dl_profile_output)
= &"/var/tmp\0/var/profile"[INTUSE(__libc_enable_secure) ? 9 : 0];
GLRO(google_ld_so_cache_list) = GOOGLE_LD_SO_CACHE_LIST;
while ((envline = _dl_next_ld_env_entry (&runp)) != NULL)
{
size_t len = 0;
@@ -2605,9 +2631,6 @@ process_envvars (enum mode *modep)
GLRO(dl_use_load_bias) = envline[14] == '1' ? -1 : 0;
break;
}
if (memcmp (envline, "POINTER_GUARD", 13) == 0)
GLRO(dl_pointer_guard) = envline[14] != '0';
break;
case 14:
@@ -2635,6 +2658,13 @@ process_envvars (enum mode *modep)
mode = trace;
break;
/* Google local change. */
case 23:
if (!INTUSE(__libc_enable_secure)
&& memcmp (envline, "GOOGLE_LD_SO_CACHE_LIST", 23) == 0)
GLRO(google_ld_so_cache_list) = &envline[24];
break;
/* We might have some extra environment variable to handle. This
is tricky due to the pre-processing of the length of the name
in the switch statement here. The code here assumes that added
@@ -2643,6 +2673,27 @@ process_envvars (enum mode *modep)
EXTRA_LD_ENVVARS
#endif
}
/* Handle all fastload-related env vars here. This may duplicate
effort with the switch table above, but it localizes changes
made by the fastload patch. On Linux, the '15' case is used
by another environment variable (LIBRARY_VERSION) and much
change would be needed to add support adding a variable of
that length with the existing style. */
switch (len)
{
case 15:
if (memcmp (envline, "FASTLOAD_CUTOFF", 15) == 0)
GLRO(dl_position_hash_cutoff)
= __strtoul_internal (&envline[16], NULL, 0, 0);;
break;
case 18:
if (memcmp (envline, "FASTLOAD_HASH_BITS", 18) == 0)
GLRO(dl_position_hash_bits)
= __strtoul_internal (&envline[19], NULL, 0, 0);;
break;
}
}
/* The caller wants this information. */
@@ -2659,6 +2710,19 @@ process_envvars (enum mode *modep)
UNSECURE_ENVVARS;
const char *nextp;
/* We may destory the connection between __environ and the auxv[]
by unsetting one or more of the insecure variables in the
original environment. Here is our last chance to record correct
__google_auxv. See b/13901604. */
extern ElfW(auxv_t) *__google_auxv;
if (__builtin_expect (__google_auxv == NULL, 1))
{
char **e;
for (e = __environ; *e; ++e) /* Skip. */;
__google_auxv = (ElfW(auxv_t) *) ++e;
}
nextp = unsecure_envvars;
do
{
@@ -2807,3 +2871,74 @@ print_statistics (hp_timing_t *rtld_total_timep)
}
#endif
}
/* Given file path, return an absolute directory path.
Examples: in: "/foo/bar/a.out", out: "/foo/bar/";
in: "./a.out", out: "/dot/resolved/to/full/path/./". */
static char *
get_directory (const char *file_path)
{
assert (file_path != NULL);
/* Find the end of the directory substring in file_path. */
size_t path_len = strlen (file_path);
while (path_len > 0 && file_path[path_len - 1] != '/')
--path_len;
/* Allocate space and set the path prefix according to whether or not
this is an absolute path. */
char *dest;
char *full_dir_path;
if (file_path[0] == '/')
{
full_dir_path = malloc (path_len + 1);
assert (full_dir_path != NULL);
dest = full_dir_path;
}
else
{
/* For a relative path, we need to include space for the largest
possible current path, a joining '/', the relevant part of
file_path, and a trailing '\0'. */
full_dir_path = malloc (PATH_MAX + path_len + 2);
assert (full_dir_path != NULL);
char *status = __getcwd (full_dir_path, PATH_MAX);
assert (status != NULL);
dest = __rawmemchr (full_dir_path, '\0');
if (dest[-1] != '/')
*dest++ = '/';
}
if (path_len > 0)
dest = __mempcpy (dest, file_path, path_len);
*dest = '\0';
return full_dir_path;
}
/* Set GLRO(google_exec_origin_dir). */
static void
set_exec_origin_dir (const char *exe_path)
{
assert (GLRO(google_exec_origin_dir) == NULL);
if (GLRO(dl_origin_path) != NULL)
GLRO(google_exec_origin_dir) = strdup (GLRO(dl_origin_path));
else if (exe_path != NULL)
GLRO(google_exec_origin_dir) = get_directory (exe_path);
}
/* Iterate over auxv, find AT_EXECFN if any. */
static char *
get_at_execfn (ElfW(auxv_t) *auxv)
{
assert (auxv != NULL);
for (; auxv->a_type != AT_NULL; ++auxv)
if (auxv->a_type == AT_EXECFN)
return (char *) auxv->a_un.a_val;
return NULL;
}
+32
View File
@@ -0,0 +1,32 @@
# Copyright (C) 2003-2013 Free Software Foundation, Inc.
# This file is part of the GNU C Library.
# The GNU C Library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# The GNU C Library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with the GNU C Library; if not, see
# <http://www.gnu.org/licenses/>.
# Makefile for google-nsl-stub add-on subdirectory of GNU C Library.
# Based on libidn/Makefile.
subdir := google-nsl-stub
extra-libs = libnsl
extra-libs-others = $(extra-libs)
libnsl-routines := ypclnt
include $(..)Makeconfig
libnsl-inhibit-o = $(filter-out .os,$(object-suffixes))
include $(..)Rules
+6
View File
@@ -0,0 +1,6 @@
# This is a shell script fragment sourced by the main configure script.
# We're obliged to give here the canonical name that will be used to
# as a subdirectory to search for in other add-ons' sysdeps trees.
libc_add_on_canonical=google-nsl-stub
libc_add_on_subdirs=.
+1
View File
@@ -0,0 +1 @@
.*-.*-.* libnsl=1
+42
View File
@@ -0,0 +1,42 @@
/* Copyright (C) 2013 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
/* This is a Google-local stub version of nis/ypclnt.c. These functions
are required for dynamic linking of some precompiled executables. */
#include <stdlib.h>
#include <stdio.h>
int yp_get_default_domain(char **domp) {
/* We duplicate glibc's error behavior and return a null pointer. */
*domp = NULL;
return 12; /* YPERR_NODOM */
}
static const char err[] = "not implemented in Google-local stub";
char *yperr_string(int incode) {
return err;
}
int yp_match(char *indomain, char *inmap, const char *inkey, int inkeylen,
char **outval, int *outvallen) {
*outval = malloc(2);
(*outval)[0] = '\n';
(*outval)[1] = '\0';
*outvallen = 0;
return 0;
}
+2 -1
View File
@@ -20,7 +20,8 @@
#
subdir := hesiod
extra-libs := libnss_hesiod
# Google-local: Disable hesiod.
# extra-libs := libnss_hesiod
extra-libs-others = $(extra-libs)
subdir-dirs = nss_hesiod
+4 -173
View File
@@ -238,181 +238,12 @@ __gconv_transliterate (struct __gconv_step *step,
return __GCONV_ILLEGAL_INPUT;
}
/* Structure to represent results of found (or not) transliteration
modules. */
struct known_trans
{
/* This structure must remain the first member. */
struct trans_struct info;
char *fname;
void *handle;
int open_count;
};
/* Tree with results of previous calls to __gconv_translit_find. */
static void *search_tree;
/* We modify global data. */
__libc_lock_define_initialized (static, lock);
/* Compare two transliteration entries. */
static int
trans_compare (const void *p1, const void *p2)
{
const struct known_trans *s1 = (const struct known_trans *) p1;
const struct known_trans *s2 = (const struct known_trans *) p2;
return strcmp (s1->info.name, s2->info.name);
}
/* Open (maybe reopen) the module named in the struct. Get the function
and data structure pointers we need. */
static int
open_translit (struct known_trans *trans)
{
__gconv_trans_query_fct queryfct;
trans->handle = __libc_dlopen (trans->fname);
if (trans->handle == NULL)
/* Not available. */
return 1;
/* Find the required symbol. */
queryfct = __libc_dlsym (trans->handle, "gconv_trans_context");
if (queryfct == NULL)
{
/* We cannot live with that. */
close_and_out:
__libc_dlclose (trans->handle);
trans->handle = NULL;
return 1;
}
/* Get the context. */
if (queryfct (trans->info.name, &trans->info.csnames, &trans->info.ncsnames)
!= 0)
goto close_and_out;
/* Of course we also have to have the actual function. */
trans->info.trans_fct = __libc_dlsym (trans->handle, "gconv_trans");
if (trans->info.trans_fct == NULL)
goto close_and_out;
/* Now the optional functions. */
trans->info.trans_init_fct =
__libc_dlsym (trans->handle, "gconv_trans_init");
trans->info.trans_context_fct =
__libc_dlsym (trans->handle, "gconv_trans_context");
trans->info.trans_end_fct =
__libc_dlsym (trans->handle, "gconv_trans_end");
trans->open_count = 1;
return 0;
}
int
internal_function
__gconv_translit_find (struct trans_struct *trans)
{
struct known_trans **found;
const struct path_elem *runp;
int res = 1;
/* We have to have a name. */
assert (trans->name != NULL);
/* Acquire the lock. */
__libc_lock_lock (lock);
/* See whether we know this module already. */
found = __tfind (trans, &search_tree, trans_compare);
if (found != NULL)
{
/* Is this module available? */
if ((*found)->handle != NULL)
{
/* Maybe we have to reopen the file. */
if ((*found)->handle != (void *) -1)
/* The object is not unloaded. */
res = 0;
else if (open_translit (*found) == 0)
{
/* Copy the data. */
*trans = (*found)->info;
(*found)->open_count++;
res = 0;
}
}
}
else
{
size_t name_len = strlen (trans->name) + 1;
int need_so = 0;
struct known_trans *newp;
/* We have to continue looking for the module. */
if (__gconv_path_elem == NULL)
__gconv_get_path ();
/* See whether we have to append .so. */
if (name_len <= 4 || memcmp (&trans->name[name_len - 4], ".so", 3) != 0)
need_so = 1;
/* Create a new entry. */
newp = (struct known_trans *) malloc (sizeof (struct known_trans)
+ (__gconv_max_path_elem_len
+ name_len + 3)
+ name_len);
if (newp != NULL)
{
char *cp;
/* Clear the struct. */
memset (newp, '\0', sizeof (struct known_trans));
/* Store a copy of the module name. */
newp->info.name = cp = (char *) (newp + 1);
cp = __mempcpy (cp, trans->name, name_len);
newp->fname = cp;
/* Search in all the directories. */
for (runp = __gconv_path_elem; runp->name != NULL; ++runp)
{
cp = __mempcpy (__stpcpy ((char *) newp->fname, runp->name),
trans->name, name_len);
if (need_so)
memcpy (cp, ".so", sizeof (".so"));
if (open_translit (newp) == 0)
{
/* We found a module. */
res = 0;
break;
}
}
if (res)
newp->fname = NULL;
/* In any case we'll add the entry to our search tree. */
if (__tsearch (newp, &search_tree, trans_compare) == NULL)
{
/* Yickes, this should not happen. Unload the object. */
res = 1;
/* XXX unload here. */
}
}
}
__libc_lock_unlock (lock);
return res;
/* Transliteration module loading has been removed because it never
worked as intended and suffered from a security vulnerability.
Consequently, this function always fails. */
return 1;
}
+1 -1
View File
@@ -16,7 +16,7 @@ extern int __libc_use_alloca (size_t size) __attribute__ ((const));
extern int __libc_alloca_cutoff (size_t size) __attribute__ ((const));
libc_hidden_proto (__libc_alloca_cutoff)
#define __MAX_ALLOCA_CUTOFF 65536
#define __MAX_ALLOCA_CUTOFF 8192
#include <allocalim.h>
+17 -1
View File
@@ -1,5 +1,6 @@
#ifndef _DLFCN_H
#include <dlfcn/dlfcn.h>
#include <sys/types.h>
#ifndef _ISOMAC
#include <link.h> /* For ElfW. */
#include <stdbool.h>
@@ -13,6 +14,10 @@
#define __RTLD_SECURE 0x04000000 /* Apply additional security checks. */
#define __RTLD_NOIFUNC 0x02000000 /* Suppress calling ifunc functions. */
/* Google-local; use only $prefix/etc/ld.so.cache.
See b/3133396 */
#define __RTLD_GOOGLE_IGNORE_HOST_LD_SO_CACHE 0x01000000
#define __LM_ID_CALLER -2
#ifdef SHARED
@@ -32,7 +37,8 @@ extern char **__libc_argv attribute_hidden;
/* Now define the internal interfaces. */
#define __libc_dlopen(name) \
__libc_dlopen_mode (name, RTLD_LAZY | __RTLD_DLOPEN)
__libc_dlopen_mode (name, RTLD_LAZY | __RTLD_DLOPEN | \
__RTLD_GOOGLE_IGNORE_HOST_LD_SO_CACHE)
extern void *__libc_dlopen_mode (const char *__name, int __mode);
extern void *__libc_dlsym (void *__map, const char *__name);
extern int __libc_dlclose (void *__map);
@@ -101,6 +107,8 @@ extern int _dlerror_run (void (*operate) (void *), void *args)
struct dlfcn_hook
{
void *(*dlopen) (const char *file, int mode, void *dl_caller);
void *(*dlopen_with_offset) (const char *file, off_t offset,
int mode, void *dl_caller);
int (*dlclose) (void *handle);
void *(*dlsym) (void *handle, const char *name, void *dl_caller);
void *(*dlvsym) (void *handle, const char *name, const char *version,
@@ -111,6 +119,8 @@ struct dlfcn_hook
void **extra_info, int flags);
int (*dlinfo) (void *handle, int request, void *arg, void *dl_caller);
void *(*dlmopen) (Lmid_t nsid, const char *file, int mode, void *dl_caller);
void *(*dlmopen_with_offset) (Lmid_t nsid, const char *file, off_t offset,
int mode, void *dl_caller);
void *pad[4];
};
@@ -119,8 +129,14 @@ libdl_hidden_proto (_dlfcn_hook)
extern void *__dlopen (const char *file, int mode DL_CALLER_DECL)
attribute_hidden;
extern void *__dlopen_with_offset (const char *file, off_t offset,
int mode DL_CALLER_DECL)
attribute_hidden;
extern void *__dlmopen (Lmid_t nsid, const char *file, int mode DL_CALLER_DECL)
attribute_hidden;
extern void *__dlmopen_with_offset (Lmid_t nsid, const char *file, off_t offset,
int mode DL_CALLER_DECL)
attribute_hidden;
extern int __dlclose (void *handle)
attribute_hidden;
extern void *__dlsym (void *handle, const char *name DL_CALLER_DECL)
+5 -1
View File
@@ -308,7 +308,8 @@
# define __USE_LARGEFILE64 1
#endif
#if defined _FILE_OFFSET_BITS && _FILE_OFFSET_BITS == 64
#if !(defined SUPPRESS_USE_FILE_OFFSET64) && defined _FILE_OFFSET_BITS && \
_FILE_OFFSET_BITS == 64
# define __USE_FILE_OFFSET64 1
#endif
@@ -372,6 +373,9 @@
#define __GLIBC_PREREQ(maj, min) \
((__GLIBC__ << 16) + __GLIBC_MINOR__ >= ((maj) << 16) + (min))
/* GRTEv4 (glibc-2.19) date */
#define __GOOGLE_GRTE_VERSION__ 20140228L
/* This is here only because every header file already includes this one. */
#ifndef __ASSEMBLER__
# ifndef _SYS_CDEFS_H
+1
View File
@@ -53,6 +53,7 @@ extern enum nss_status _nss_ ## service ##_initgroups_dyn \
long int *size, gid_t **groupsp, long int limit, \
int *errnop);
DECLARE_NSS_PROTOTYPES (cache)
DECLARE_NSS_PROTOTYPES (compat)
DECLARE_NSS_PROTOTYPES (files)
DECLARE_NSS_PROTOTYPES (hesiod)
+6
View File
@@ -238,6 +238,12 @@ struct link_map
dev_t l_dev;
ino64_t l_ino;
/* Google-specific extension, intended to be part of public interface
to the debugger. As such, it belongs right after l_prev... except
putting it there causes Google libunwind to crash due to its own
peeking into glibc internals (see grte_v1_glibc_link_map). */
size_t l_off; /* File offset to Elf_Ehdr. */
/* Collected information about own RUNPATH directories. */
struct r_search_path_struct l_runpath_dirs;
+2
View File
@@ -45,8 +45,10 @@ extern enum nss_status _nss_ ## service ##_getpwent_r \
(struct passwd *result, char *buffer, \
size_t buflen, int *errnop);
DECLARE_NSS_PROTOTYPES (cache)
DECLARE_NSS_PROTOTYPES (compat)
DECLARE_NSS_PROTOTYPES (files)
DECLARE_NSS_PROTOTYPES (borg)
DECLARE_NSS_PROTOTYPES (hesiod)
DECLARE_NSS_PROTOTYPES (nis)
DECLARE_NSS_PROTOTYPES (nisplus)
+3 -3
View File
@@ -48,11 +48,11 @@ libc_hidden_proto (__res_randomid)
libc_hidden_proto (__res_state)
int __libc_res_nquery (res_state, const char *, int, int, u_char *, int,
u_char **, u_char **, int *, int *);
u_char **, u_char **, int *, int *, int *);
int __libc_res_nsearch (res_state, const char *, int, int, u_char *, int,
u_char **, u_char **, int *, int *);
u_char **, u_char **, int *, int *, int *);
int __libc_res_nsend (res_state, const u_char *, int, const u_char *, int,
u_char *, int, u_char **, u_char **, int *, int *)
u_char *, int, u_char **, u_char **, int *, int *, int *)
attribute_hidden;
libresolv_hidden_proto (_sethtent)
+1
View File
@@ -38,6 +38,7 @@ extern enum nss_status _nss_ ## service ## _getspnam_r \
(const char *name, struct spwd *pwd, \
char *buffer, size_t buflen, int *errnop);
DECLARE_NSS_PROTOTYPES (cache)
DECLARE_NSS_PROTOTYPES (compat)
DECLARE_NSS_PROTOTYPES (files)
DECLARE_NSS_PROTOTYPES (hesiod)
+18
View File
@@ -203,6 +203,24 @@ libc_hidden_proto (strtoll)
libc_hidden_proto (strtoul)
libc_hidden_proto (strtoull)
extern float __strtof_nan (const char *, char **, char) internal_function;
extern double __strtod_nan (const char *, char **, char) internal_function;
extern long double __strtold_nan (const char *, char **, char)
internal_function;
extern float __wcstof_nan (const wchar_t *, wchar_t **, wchar_t)
internal_function;
extern double __wcstod_nan (const wchar_t *, wchar_t **, wchar_t)
internal_function;
extern long double __wcstold_nan (const wchar_t *, wchar_t **, wchar_t)
internal_function;
libc_hidden_proto (__strtof_nan)
libc_hidden_proto (__strtod_nan)
libc_hidden_proto (__strtold_nan)
libc_hidden_proto (__wcstof_nan)
libc_hidden_proto (__wcstod_nan)
libc_hidden_proto (__wcstold_nan)
extern char *__ecvt (double __value, int __ndigit, int *__restrict __decpt,
int *__restrict __sign);
extern char *__fcvt (double __value, int __ndigit, int *__restrict __decpt,
+3
View File
@@ -52,6 +52,9 @@ extern unsigned long long int __wcstoull_internal (const wchar_t *
__restrict __endptr,
int __base,
int __group) __THROW;
extern unsigned long long int ____wcstoull_l_internal (const wchar_t *,
wchar_t **, int, int,
__locale_t);
libc_hidden_proto (__wcstof_internal)
libc_hidden_proto (__wcstod_internal)
libc_hidden_proto (__wcstold_internal)
+5 -1
View File
@@ -60,7 +60,8 @@ tests = tst_swprintf tst_wprintf tst_swscanf tst_wscanf tst_getwc tst_putwc \
tst-wmemstream1 tst-wmemstream2 \
bug-memstream1 bug-wmemstream1 \
tst-setvbuf1 tst-popen1 tst-fgetwc bug-wsetpos tst-fseek \
tst-fwrite-error tst-ftell-partial-wide
tst-fwrite-error tst-ftell-partial-wide tst-ftell-active-handler \
tst-ftell-append
ifeq (yes,$(build-shared))
# Add test-fopenloc only if shared library is enabled since it depends on
# shared localedata objects.
@@ -160,6 +161,9 @@ tst-swscanf-ENV = LOCPATH=$(common-objpfx)localedata
bug-ftell-ENV = LOCPATH=$(common-objpfx)localedata
tst-fgetwc-ENV = LOCPATH=$(common-objpfx)localedata
tst-fseek-ENV = LOCPATH=$(common-objpfx)localedata
tst-ftell-partial-wide-ENV = LOCPATH=$(common-objpfx)localedata
tst-ftell-active-handler-ENV = LOCPATH=$(common-objpfx)localedata
tst-ftell-append-ENV = LOCPATH=$(common-objpfx)localedata
generated = tst-fopenloc.mtrace tst-fopenloc.check
+87 -38
View File
@@ -91,7 +91,9 @@ extern struct __gconv_trans_data __libio_translit attribute_hidden;
The position in the buffer that corresponds to the position
in external file system is normally _IO_read_end, except in putback
mode, when it is _IO_save_end.
mode, when it is _IO_save_end and also when the file is in append mode,
since switching from read to write mode automatically sends the position in
the external file system to the end of file.
If the field _fb._offset is >= 0, it gives the offset in
the file as a whole corresponding to eGptr(). (?)
@@ -232,13 +234,18 @@ _IO_file_open (fp, filename, posix_mode, prot, read_write, is32not64)
return NULL;
fp->_fileno = fdesc;
_IO_mask_flags (fp, read_write,_IO_NO_READS+_IO_NO_WRITES+_IO_IS_APPENDING);
if ((read_write & _IO_IS_APPENDING) && (read_write & _IO_NO_READS))
if (_IO_SEEKOFF (fp, (_IO_off64_t)0, _IO_seek_end, _IOS_INPUT|_IOS_OUTPUT)
== _IO_pos_BAD && errno != ESPIPE)
{
close_not_cancel (fdesc);
return NULL;
}
/* For append mode, send the file offset to the end of the file. Don't
update the offset cache though, since the file handle is not active. */
if ((read_write & (_IO_IS_APPENDING | _IO_NO_READS))
== (_IO_IS_APPENDING | _IO_NO_READS))
{
_IO_off64_t new_pos = _IO_SYSSEEK (fp, 0, _IO_seek_end);
if (new_pos == _IO_pos_BAD && errno != ESPIPE)
{
close_not_cancel (fdesc);
return NULL;
}
}
_IO_link_in ((struct _IO_FILE_plus *) fp);
return fp;
}
@@ -929,6 +936,68 @@ _IO_file_sync_mmap (_IO_FILE *fp)
return 0;
}
/* ftell{,o} implementation. The only time we modify the state of the stream
is when we have unflushed writes. In that case we seek to the end and
record that offset in the stream object. */
static _IO_off64_t
do_ftell (_IO_FILE *fp)
{
_IO_off64_t result, offset = 0;
/* No point looking at unflushed data if we haven't allocated buffers
yet. */
if (fp->_IO_buf_base != NULL)
{
bool was_writing = (fp->_IO_write_ptr > fp->_IO_write_base
|| _IO_in_put_mode (fp));
bool append_mode = (fp->_flags & _IO_IS_APPENDING) == _IO_IS_APPENDING;
/* When we have unflushed writes in append mode, seek to the end of the
file and record that offset. This is the only time we change the file
stream state and it is safe since the file handle is active. */
if (was_writing && append_mode)
{
result = _IO_SYSSEEK (fp, 0, _IO_seek_end);
if (result == _IO_pos_BAD)
return EOF;
else
fp->_offset = result;
}
/* Adjust for unflushed data. */
if (!was_writing)
offset -= fp->_IO_read_end - fp->_IO_read_ptr;
/* We don't trust _IO_read_end to represent the current file offset when
writing in append mode because the value would have to be shifted to
the end of the file during a flush. Use the write base instead, along
with the new offset we got above when we did a seek to the end of the
file. */
else if (append_mode)
offset += fp->_IO_write_ptr - fp->_IO_write_base;
/* For all other modes, _IO_read_end represents the file offset. */
else
offset += fp->_IO_write_ptr - fp->_IO_read_end;
}
if (fp->_offset != _IO_pos_BAD)
result = fp->_offset;
else
result = _IO_SYSSEEK (fp, 0, _IO_seek_cur);
if (result == EOF)
return result;
result += offset;
if (result < 0)
{
__set_errno (EINVAL);
return EOF;
}
return result;
}
_IO_off64_t
_IO_new_file_seekoff (fp, offset, dir, mode)
@@ -940,6 +1009,13 @@ _IO_new_file_seekoff (fp, offset, dir, mode)
_IO_off64_t result;
_IO_off64_t delta, new_offset;
long count;
/* Short-circuit into a separate function. We don't want to mix any
functionality and we don't want to touch anything inside the FILE
object. */
if (mode == 0)
return do_ftell (fp);
/* POSIX.1 8.2.3.7 says that after a call the fflush() the file
offset of the underlying file must be exact. */
int must_be_exact = (fp->_IO_read_base == fp->_IO_read_end
@@ -948,9 +1024,6 @@ _IO_new_file_seekoff (fp, offset, dir, mode)
bool was_writing = (fp->_IO_write_ptr > fp->_IO_write_base
|| _IO_in_put_mode (fp));
if (mode == 0)
dir = _IO_seek_cur, offset = 0; /* Don't move any pointers. */
/* Flush unwritten characters.
(This may do an unneeded write if we seek within the buffer.
But to be able to switch to reading, we would need to set
@@ -958,7 +1031,7 @@ _IO_new_file_seekoff (fp, offset, dir, mode)
which assumes file_ptr() is eGptr. Anyway, since we probably
end up flushing when we close(), it doesn't make much difference.)
FIXME: simulate mem-mapped files. */
else if (was_writing && _IO_switch_to_get_mode (fp))
if (was_writing && _IO_switch_to_get_mode (fp))
return EOF;
if (fp->_IO_buf_base == NULL)
@@ -978,30 +1051,10 @@ _IO_new_file_seekoff (fp, offset, dir, mode)
{
case _IO_seek_cur:
/* Adjust for read-ahead (bytes is buffer). */
if (mode != 0 || !was_writing)
offset -= fp->_IO_read_end - fp->_IO_read_ptr;
else
{
/* _IO_read_end coincides with fp._offset, so the actual file position
is fp._offset - (_IO_read_end - new_write_ptr). This is fine
even if fp._offset is not set, since fp->_IO_read_end is then at
_IO_buf_base and this adjustment is for unbuffered output. */
offset -= fp->_IO_read_end - fp->_IO_write_ptr;
}
offset -= fp->_IO_read_end - fp->_IO_read_ptr;
if (fp->_offset == _IO_pos_BAD)
{
if (mode != 0)
goto dumb;
else
{
result = _IO_SYSSEEK (fp, 0, dir);
if (result == EOF)
return result;
fp->_offset = result;
}
}
goto dumb;
/* Make offset absolute, assuming current pointer is file_ptr(). */
offset += fp->_offset;
if (offset < 0)
@@ -1028,10 +1081,6 @@ _IO_new_file_seekoff (fp, offset, dir, mode)
}
/* At this point, dir==_IO_seek_set. */
/* If we are only interested in the current position we've found it now. */
if (mode == 0)
return offset;
/* If destination is within current buffer, optimize: */
if (fp->_offset != _IO_pos_BAD && fp->_IO_read_base != NULL
&& !_IO_in_backup (fp))
+1 -1
View File
@@ -124,7 +124,7 @@ fmemopen_write (void *cookie, const char *b, size_t s)
if (c->pos + s + addnullc > c->size)
{
if ((size_t) (c->pos + addnullc) == c->size)
if ((size_t) (c->pos + addnullc) >= c->size)
{
__set_errno (ENOSPC);
return 0;
+15 -10
View File
@@ -141,9 +141,6 @@ _IO_new_fdopen (fd, mode)
#ifdef _IO_MTSAFE_IO
new_f->fp.file._lock = &new_f->lock;
#endif
/* Set up initially to use the `maybe_mmap' jump tables rather than using
__fopen_maybe_mmap to do it, because we need them in place before we
call _IO_file_attach or else it will allocate a buffer immediately. */
_IO_no_init (&new_f->fp.file, 0, 0, &new_f->wd,
#ifdef _G_HAVE_MMAP
(use_mmap && (read_write & _IO_NO_WRITES))
@@ -159,18 +156,26 @@ _IO_new_fdopen (fd, mode)
#if !_IO_UNIFIED_JUMPTABLES
new_f->fp.vtable = NULL;
#endif
if (_IO_file_attach ((_IO_FILE *) &new_f->fp, fd) == NULL)
{
_IO_setb (&new_f->fp.file, NULL, NULL, 0);
_IO_un_link (&new_f->fp);
free (new_f);
return NULL;
}
/* We only need to record the fd because _IO_file_init will have unset the
offset. It is important to unset the cached offset because the real
offset in the file could change between now and when the handle is
activated and we would then mislead ftell into believing that we have a
valid offset. */
new_f->fp.file._fileno = fd;
new_f->fp.file._flags &= ~_IO_DELETE_DONT_CLOSE;
_IO_mask_flags (&new_f->fp.file, read_write,
_IO_NO_READS+_IO_NO_WRITES+_IO_IS_APPENDING);
/* For append mode, set the file offset to the end of the file. Don't
update the offset cache though, since the file handle is not active. */
if ((read_write & (_IO_IS_APPENDING | _IO_NO_READS))
== (_IO_IS_APPENDING | _IO_NO_READS))
{
_IO_off64_t new_pos = _IO_SYSSEEK (&new_f->fp.file, 0, _IO_seek_end);
if (new_pos == _IO_pos_BAD && errno != ESPIPE)
return NULL;
}
return &new_f->fp.file;
}
libc_hidden_ver (_IO_new_fdopen, _IO_fdopen)
-6
View File
@@ -199,12 +199,6 @@ _IO_fwide (fp, mode)
/* From now on use the wide character callback functions. */
((struct _IO_FILE_plus *) fp)->vtable = fp->_wide_data->_wide_vtable;
/* One last twist: we get the current stream position. The wide
char streams have much more problems with not knowing the
current position and so we should disable the optimization
which allows the functions without knowing the position. */
fp->_offset = _IO_SYSSEEK (fp, 0, _IO_seek_cur);
}
/* Set the mode now. */
+1
View File
@@ -397,6 +397,7 @@ extern void _IO_wdoallocbuf (_IO_FILE *) __THROW;
libc_hidden_proto (_IO_wdoallocbuf)
extern void _IO_unsave_wmarkers (_IO_FILE *) __THROW;
extern unsigned _IO_adjust_wcolumn (unsigned, const wchar_t *, int) __THROW;
extern _IO_off64_t get_file_offset (_IO_FILE *fp);
/* Marker-related function. */
+17 -5
View File
@@ -1,5 +1,5 @@
/* Test for fmemopen implementation.
Copyright (C) 2000-2014 Free Software Foundation, Inc.
Copyright (C) 2000-2015 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Hanno Mueller, kontakt@hanno.de, 2000.
@@ -21,19 +21,31 @@ static char buffer[] = "foobar";
#include <stdio.h>
#include <string.h>
#include <errno.h>
int
main (void)
static int
do_test (void)
{
int ch;
FILE *stream;
int ret = 0;
stream = fmemopen (buffer, strlen (buffer), "r");
stream = fmemopen (buffer, strlen (buffer), "r+");
while ((ch = fgetc (stream)) != EOF)
printf ("Got %c\n", ch);
fputc ('1', stream);
if (fflush (stream) != EOF || errno != ENOSPC)
{
printf ("fflush didn't fail with ENOSPC\n");
ret = 1;
}
fclose (stream);
return 0;
return ret;
}
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"
+488
View File
@@ -0,0 +1,488 @@
/* Verify that ftell returns the correct value at various points before and
after the handler on which it is called becomes active.
Copyright (C) 2014 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <locale.h>
#include <wchar.h>
static int do_test (void);
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"
#define get_handles_fdopen(filename, fd, fp, fd_mode, mode) \
({ \
int ret = 0; \
(fd) = open ((filename), (fd_mode), 0); \
if ((fd) == -1) \
{ \
printf ("open failed: %m\n"); \
ret = 1; \
} \
else \
{ \
(fp) = fdopen ((fd), (mode)); \
if ((fp) == NULL) \
{ \
printf ("fdopen failed: %m\n"); \
close (fd); \
ret = 1; \
} \
} \
ret; \
})
#define get_handles_fopen(filename, fd, fp, mode) \
({ \
int ret = 0; \
(fp) = fopen ((filename), (mode)); \
if ((fp) == NULL) \
{ \
printf ("fopen failed: %m\n"); \
ret = 1; \
} \
else \
{ \
(fd) = fileno (fp); \
if ((fd) == -1) \
{ \
printf ("fileno failed: %m\n"); \
ret = 1; \
} \
} \
ret; \
})
/* data points to either char_data or wide_data, depending on whether we're
testing regular file mode or wide mode respectively. Similarly,
fputs_func points to either fputs or fputws. data_len keeps track of the
length of the current data and file_len maintains the current file
length. */
static const void *data;
static const char *char_data = "abcdef";
static const wchar_t *wide_data = L"abcdef";
static size_t data_len;
static size_t file_len;
typedef int (*fputs_func_t) (const void *data, FILE *fp);
fputs_func_t fputs_func;
/* Test that ftell output after a rewind is correct. */
static int
do_rewind_test (const char *filename)
{
int ret = 0;
struct test
{
const char *mode;
int fd_mode;
size_t old_off;
size_t new_off;
} test_modes[] = {
{"w", O_WRONLY, 0, data_len},
{"w+", O_RDWR, 0, data_len},
{"r+", O_RDWR, 0, data_len},
/* The new offsets for 'a' and 'a+' modes have to factor in the
previous writes since they always append to the end of the
file. */
{"a", O_WRONLY, 0, 3 * data_len},
{"a+", O_RDWR, 0, 4 * data_len},
};
/* Empty the file before the test so that our offsets are simple to
calculate. */
FILE *fp = fopen (filename, "w");
if (fp == NULL)
{
printf ("Failed to open file for emptying\n");
return 1;
}
fclose (fp);
for (int j = 0; j < 2; j++)
{
for (int i = 0; i < sizeof (test_modes) / sizeof (struct test); i++)
{
FILE *fp;
int fd;
int fileret;
printf ("\trewind: %s (file, \"%s\"): ", j == 0 ? "fdopen" : "fopen",
test_modes[i].mode);
if (j == 0)
fileret = get_handles_fdopen (filename, fd, fp,
test_modes[i].fd_mode,
test_modes[i].mode);
else
fileret = get_handles_fopen (filename, fd, fp, test_modes[i].mode);
if (fileret != 0)
return fileret;
/* Write some content to the file, rewind and ensure that the ftell
output after the rewind is 0. POSIX does not specify what the
behavior is when a file is rewound in 'a' mode, so we retain
current behavior, which is to keep the 0 offset. */
size_t written = fputs_func (data, fp);
if (written == EOF)
{
printf ("fputs[1] failed to write data\n");
ret |= 1;
}
rewind (fp);
long offset = ftell (fp);
if (offset != test_modes[i].old_off)
{
printf ("Incorrect old offset. Expected %zu, but got %ld, ",
test_modes[i].old_off, offset);
ret |= 1;
}
else
printf ("old offset = %ld, ", offset);
written = fputs_func (data, fp);
if (written == EOF)
{
printf ("fputs[1] failed to write data\n");
ret |= 1;
}
/* After this write, the offset in append modes should factor in the
implicit lseek to the end of file. */
offset = ftell (fp);
if (offset != test_modes[i].new_off)
{
printf ("Incorrect new offset. Expected %zu, but got %ld\n",
test_modes[i].new_off, offset);
ret |= 1;
}
else
printf ("new offset = %ld\n", offset);
}
}
return ret;
}
/* Test that the value of ftell is not cached when the stream handle is not
active. */
static int
do_ftell_test (const char *filename)
{
int ret = 0;
struct test
{
const char *mode;
int fd_mode;
size_t old_off;
size_t new_off;
} test_modes[] = {
/* In w, w+ and r+ modes, the file position should be at the
beginning of the file. After the write, the offset should be
updated to data_len. */
{"w", O_WRONLY, 0, data_len},
{"w+", O_RDWR, 0, data_len},
{"r+", O_RDWR, 0, data_len},
/* For the 'a' mode, the initial file position should be the
current end of file. After the write, the offset has data_len
added to the old value. For a+ mode however, the initial file
position is the file position of the underlying file descriptor,
since it is initially assumed to be in read mode. */
{"a", O_WRONLY, data_len, 2 * data_len},
{"a+", O_RDWR, 0, 3 * data_len},
};
for (int j = 0; j < 2; j++)
{
for (int i = 0; i < sizeof (test_modes) / sizeof (struct test); i++)
{
FILE *fp;
int fd;
printf ("\tftell: %s (file, \"%s\"): ", j == 0 ? "fdopen" : "fopen",
test_modes[i].mode);
if (j == 0)
ret = get_handles_fdopen (filename, fd, fp, test_modes[i].fd_mode,
test_modes[i].mode);
else
ret = get_handles_fopen (filename, fd, fp, test_modes[i].mode);
if (ret != 0)
return ret;
long off = ftell (fp);
if (off != test_modes[i].old_off)
{
printf ("Incorrect old offset. Expected %zu but got %ld, ",
test_modes[i].old_off, off);
ret |= 1;
}
else
printf ("old offset = %ld, ", off);
/* The effect of this write on the offset should be seen in the ftell
call that follows it. */
int ret = write (fd, data, data_len);
off = ftell (fp);
if (off != test_modes[i].new_off)
{
printf ("Incorrect new offset. Expected %zu but got %ld\n",
test_modes[i].new_off, off);
ret |= 1;
}
else
printf ("new offset = %ld\n", off);
fclose (fp);
}
}
return ret;
}
/* This test opens the file for writing, moves the file offset of the
underlying file, writes out data and then checks if ftell trips on it. */
static int
do_write_test (const char *filename)
{
FILE *fp = NULL;
int fd;
int ret = 0;
struct test
{
const char *mode;
int fd_mode;
} test_modes[] = {
{"w", O_WRONLY},
{"w+", O_RDWR},
{"r+", O_RDWR}
};
for (int j = 0; j < 2; j++)
{
for (int i = 0; i < sizeof (test_modes) / sizeof (struct test); i++)
{
printf ("\twrite: %s (file, \"%s\"): ", j == 0 ? "fopen" : "fdopen",
test_modes[i].mode);
if (j == 0)
ret = get_handles_fopen (filename, fd, fp, test_modes[i].mode);
else
ret = get_handles_fdopen (filename, fd, fp, test_modes[i].fd_mode,
test_modes[i].mode);
if (ret != 0)
return ret;
/* Move offset to just before the end of the file. */
off_t ret = lseek (fd, file_len - 1, SEEK_SET);
if (ret == -1)
{
printf ("lseek failed: %m\n");
ret |= 1;
}
/* Write some data. */
size_t written = fputs_func (data, fp);
if (written == EOF)
{
printf ("fputs[1] failed to write data\n");
ret |= 1;
}
/* Verify that the offset points to the end of the file. The length
of the file would be the original length + the length of data
written to it - the amount by which we moved the offset using
lseek. */
long offset = ftell (fp);
file_len = file_len - 1 + data_len;
if (offset != file_len)
{
printf ("Incorrect offset. Expected %zu, but got %ld\n",
file_len, offset);
ret |= 1;
}
printf ("offset = %ld\n", offset);
fclose (fp);
}
}
return ret;
}
/* This test opens a file in append mode, writes some data, and then verifies
that ftell does not trip over it. */
static int
do_append_test (const char *filename)
{
FILE *fp = NULL;
int ret = 0;
int fd;
struct test
{
const char *mode;
int fd_mode;
} test_modes[] = {
{"a", O_WRONLY},
{"a+", O_RDWR}
};
for (int j = 0; j < 2; j++)
{
for (int i = 0; i < sizeof (test_modes) / sizeof (struct test); i++)
{
printf ("\tappend: %s (file, \"%s\"): ", j == 0 ? "fopen" : "fdopen",
test_modes[i].mode);
if (j == 0)
ret = get_handles_fopen (filename, fd, fp, test_modes[i].mode);
else
ret = get_handles_fdopen (filename, fd, fp, test_modes[i].fd_mode,
test_modes[i].mode);
if (ret != 0)
return ret;
/* Write some data. */
size_t written = fputs_func (data, fp);
if (written == EOF)
{
printf ("fputs[1] failed to write all data\n");
ret |= 1;
}
/* Verify that the offset points to the end of the file. The file
len is maintained by adding data_len each time to reflect the data
written to it. */
long offset = ftell (fp);
file_len += data_len;
if (offset != file_len)
{
printf ("Incorrect offset. Expected %zu, but got %ld\n",
file_len, offset);
ret |= 1;
}
printf ("offset = %ld\n", offset);
fclose (fp);
}
}
return ret;
}
static int
do_one_test (const char *filename)
{
int ret = 0;
ret |= do_ftell_test (filename);
ret |= do_write_test (filename);
ret |= do_append_test (filename);
ret |= do_rewind_test (filename);
return ret;
}
/* Run a set of tests for ftell for regular files and wide mode files. */
static int
do_test (void)
{
int ret = 0;
FILE *fp = NULL;
char *filename;
size_t written;
int fd = create_temp_file ("tst-active-handler-tmp.", &filename);
if (fd == -1)
{
printf ("create_temp_file: %m\n");
return 1;
}
fp = fdopen (fd, "w");
if (fp == NULL)
{
printf ("fdopen[0]: %m\n");
close (fd);
return 1;
}
data = char_data;
data_len = strlen (char_data);
file_len = strlen (char_data);
written = fputs (data, fp);
if (written == EOF)
{
printf ("fputs[1] failed to write data\n");
ret = 1;
}
fclose (fp);
if (ret)
return ret;
/* Tests for regular files. */
puts ("Regular mode:");
fputs_func = (fputs_func_t) fputs;
data = char_data;
data_len = strlen (char_data);
ret |= do_one_test (filename);
/* Truncate the file before repeating the tests in wide mode. */
fp = fopen (filename, "w");
if (fp == NULL)
{
printf ("fopen failed %m\n");
return 1;
}
fclose (fp);
/* Tests for wide files. */
puts ("Wide mode:");
if (setlocale (LC_ALL, "en_US.UTF-8") == NULL)
{
printf ("Cannot set en_US.UTF-8 locale.\n");
return 1;
}
fputs_func = (fputs_func_t) fputws;
data = wide_data;
data_len = wcslen (wide_data);
ret |= do_one_test (filename);
return ret;
}
+169
View File
@@ -0,0 +1,169 @@
/* Verify that ftell returns the correct value after a read and a write on a
file opened in a+ mode.
Copyright (C) 2014 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <locale.h>
#include <wchar.h>
/* data points to either char_data or wide_data, depending on whether we're
testing regular file mode or wide mode respectively. Similarly,
fputs_func points to either fputs or fputws. data_len keeps track of the
length of the current data and file_len maintains the current file
length. */
#define BUF_LEN 4
static void *buf;
static char char_buf[BUF_LEN];
static wchar_t wide_buf[BUF_LEN];
static const void *data;
static const char *char_data = "abcdefghijklmnopqrstuvwxyz";
static const wchar_t *wide_data = L"abcdefghijklmnopqrstuvwxyz";
static size_t data_len;
static size_t file_len;
typedef int (*fputs_func_t) (const void *data, FILE *fp);
fputs_func_t fputs_func;
typedef void *(*fgets_func_t) (void *s, int size, FILE *stream);
fgets_func_t fgets_func;
static int do_test (void);
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"
static FILE *
init_file (const char *filename)
{
FILE *fp = fopen (filename, "w");
if (fp == NULL)
{
printf ("fopen: %m\n");
return NULL;
}
int written = fputs_func (data, fp);
if (written == EOF)
{
printf ("fputs failed to write data\n");
fclose (fp);
return NULL;
}
file_len = data_len;
fclose (fp);
fp = fopen (filename, "a+");
if (fp == NULL)
{
printf ("fopen(a+): %m\n");
return NULL;
}
return fp;
}
static int
do_one_test (const char *filename)
{
FILE *fp = init_file (filename);
if (fp == NULL)
return 1;
void *ret = fgets_func (buf, BUF_LEN, fp);
if (ret == NULL)
{
printf ("read failed: %m\n");
fclose (fp);
return 1;
}
int written = fputs_func (data, fp);
if (written == EOF)
{
printf ("fputs failed to write data\n");
fclose (fp);
return 1;
}
file_len += data_len;
long off = ftell (fp);
if (off != file_len)
{
printf ("Incorrect offset %ld, expected %zu\n", off, file_len);
fclose (fp);
return 1;
}
else
printf ("Correct offset %ld after write.\n", off);
return 0;
}
/* Run the tests for regular files and wide mode files. */
static int
do_test (void)
{
int ret = 0;
char *filename;
int fd = create_temp_file ("tst-ftell-append-tmp.", &filename);
if (fd == -1)
{
printf ("create_temp_file: %m\n");
return 1;
}
close (fd);
/* Tests for regular files. */
puts ("Regular mode:");
fputs_func = (fputs_func_t) fputs;
fgets_func = (fgets_func_t) fgets;
data = char_data;
buf = char_buf;
data_len = strlen (char_data);
ret |= do_one_test (filename);
/* Tests for wide files. */
puts ("Wide mode:");
if (setlocale (LC_ALL, "en_US.UTF-8") == NULL)
{
printf ("Cannot set en_US.UTF-8 locale.\n");
return 1;
}
fputs_func = (fputs_func_t) fputws;
fgets_func = (fgets_func_t) fgetws;
data = wide_data;
buf = wide_buf;
data_len = wcslen (wide_data);
ret |= do_one_test (filename);
return ret;
}
+158 -102
View File
@@ -596,29 +596,39 @@ done:
return 0;
}
_IO_off64_t
_IO_wfile_seekoff (fp, offset, dir, mode)
_IO_FILE *fp;
_IO_off64_t offset;
int dir;
int mode;
/* ftell{,o} implementation for wide mode. Don't modify any state of the file
pointer while we try to get the current state of the stream except in one
case, which is when we have unflushed writes in append mode. */
static _IO_off64_t
do_ftell_wide (_IO_FILE *fp)
{
_IO_off64_t result;
_IO_off64_t delta, new_offset;
long int count;
/* POSIX.1 8.2.3.7 says that after a call the fflush() the file
offset of the underlying file must be exact. */
int must_be_exact = ((fp->_wide_data->_IO_read_base
== fp->_wide_data->_IO_read_end)
&& (fp->_wide_data->_IO_write_base
== fp->_wide_data->_IO_write_ptr));
_IO_off64_t result, offset = 0;
bool was_writing = ((fp->_wide_data->_IO_write_ptr
> fp->_wide_data->_IO_write_base)
|| _IO_in_put_mode (fp));
if (mode == 0)
/* No point looking for offsets in the buffer if it hasn't even been
allocated. */
if (fp->_wide_data->_IO_buf_base != NULL)
{
const wchar_t *wide_read_base;
const wchar_t *wide_read_ptr;
const wchar_t *wide_read_end;
bool was_writing = ((fp->_wide_data->_IO_write_ptr
> fp->_wide_data->_IO_write_base)
|| _IO_in_put_mode (fp));
bool append_mode = (fp->_flags & _IO_IS_APPENDING) == _IO_IS_APPENDING;
/* When we have unflushed writes in append mode, seek to the end of the
file and record that offset. This is the only time we change the file
stream state and it is safe since the file handle is active. */
if (was_writing && append_mode)
{
result = _IO_SYSSEEK (fp, 0, _IO_seek_end);
if (result == _IO_pos_BAD)
return EOF;
else
fp->_offset = result;
}
/* XXX For wide stream with backup store it is not very
reasonable to determine the offset. The pushed-back
character might require a state change and we need not be
@@ -633,14 +643,136 @@ _IO_wfile_seekoff (fp, offset, dir, mode)
return -1;
}
/* There is no more data in the backup buffer. We can
switch back. */
_IO_switch_to_main_wget_area (fp);
/* Nothing in the backup store, so note the backed up pointers
without changing the state. */
wide_read_base = fp->_wide_data->_IO_save_base;
wide_read_ptr = wide_read_base;
wide_read_end = fp->_wide_data->_IO_save_end;
}
else
{
wide_read_base = fp->_wide_data->_IO_read_base;
wide_read_ptr = fp->_wide_data->_IO_read_ptr;
wide_read_end = fp->_wide_data->_IO_read_end;
}
dir = _IO_seek_cur, offset = 0; /* Don't move any pointers. */
struct _IO_codecvt *cv = fp->_codecvt;
int clen = (*cv->__codecvt_do_encoding) (cv);
if (!was_writing)
{
if (clen > 0)
{
offset -= (wide_read_end - wide_read_ptr) * clen;
offset -= fp->_IO_read_end - fp->_IO_read_ptr;
}
else
{
int nread;
size_t delta = wide_read_ptr - wide_read_base;
__mbstate_t state = fp->_wide_data->_IO_last_state;
nread = (*cv->__codecvt_do_length) (cv, &state,
fp->_IO_read_base,
fp->_IO_read_end, delta);
offset -= fp->_IO_read_end - fp->_IO_read_base - nread;
}
}
else
{
if (clen > 0)
offset += (fp->_wide_data->_IO_write_ptr
- fp->_wide_data->_IO_write_base) * clen;
else
{
size_t delta = (fp->_wide_data->_IO_write_ptr
- fp->_wide_data->_IO_write_base);
/* Allocate enough space for the conversion. */
size_t outsize = delta * sizeof (wchar_t);
char *out = malloc (outsize);
char *outstop = out;
const wchar_t *in = fp->_wide_data->_IO_write_base;
enum __codecvt_result status;
__mbstate_t state = fp->_wide_data->_IO_last_state;
status = (*cv->__codecvt_do_out) (cv, &state,
in, in + delta, &in,
out, out + outsize, &outstop);
/* We don't check for __codecvt_partial because it can be
returned on one of two conditions: either the output
buffer is full or the input sequence is incomplete. We
take care to allocate enough buffer and our input
sequences must be complete since they are accepted as
wchar_t; if not, then that is an error. */
if (__glibc_unlikely (status != __codecvt_ok))
return WEOF;
offset += outstop - out;
}
/* We don't trust _IO_read_end to represent the current file offset
when writing in append mode because the value would have to be
shifted to the end of the file during a flush. Use the write base
instead, along with the new offset we got above when we did a seek
to the end of the file. */
if (append_mode)
offset += fp->_IO_write_ptr - fp->_IO_write_base;
/* For all other modes, _IO_read_end represents the file offset. */
else
offset += fp->_IO_write_ptr - fp->_IO_read_end;
}
}
if (fp->_offset != _IO_pos_BAD)
result = fp->_offset;
else
result = _IO_SYSSEEK (fp, 0, _IO_seek_cur);
if (result == EOF)
return result;
result += offset;
if (result < 0)
{
__set_errno (EINVAL);
return EOF;
}
return result;
}
_IO_off64_t
_IO_wfile_seekoff (fp, offset, dir, mode)
_IO_FILE *fp;
_IO_off64_t offset;
int dir;
int mode;
{
_IO_off64_t result;
_IO_off64_t delta, new_offset;
long int count;
/* Short-circuit into a separate function. We don't want to mix any
functionality and we don't want to touch anything inside the FILE
object. */
if (mode == 0)
return do_ftell_wide (fp);
/* POSIX.1 8.2.3.7 says that after a call the fflush() the file
offset of the underlying file must be exact. */
int must_be_exact = ((fp->_wide_data->_IO_read_base
== fp->_wide_data->_IO_read_end)
&& (fp->_wide_data->_IO_write_base
== fp->_wide_data->_IO_write_ptr));
bool was_writing = ((fp->_wide_data->_IO_write_ptr
> fp->_wide_data->_IO_write_base)
|| _IO_in_put_mode (fp));
/* Flush unwritten characters.
(This may do an unneeded write if we seek within the buffer.
But to be able to switch to reading, we would need to set
@@ -648,7 +780,7 @@ _IO_wfile_seekoff (fp, offset, dir, mode)
which assumes file_ptr() is eGptr. Anyway, since we probably
end up flushing when we close(), it doesn't make much difference.)
FIXME: simulate mem-mapped files. */
else if (was_writing && _IO_switch_to_wget_mode (fp))
if (was_writing && _IO_switch_to_wget_mode (fp))
return WEOF;
if (fp->_wide_data->_IO_buf_base == NULL)
@@ -693,7 +825,6 @@ _IO_wfile_seekoff (fp, offset, dir, mode)
{
int nread;
flushed:
delta = (fp->_wide_data->_IO_read_ptr
- fp->_wide_data->_IO_read_base);
fp->_wide_data->_IO_state = fp->_wide_data->_IO_last_state;
@@ -706,80 +837,9 @@ _IO_wfile_seekoff (fp, offset, dir, mode)
offset -= fp->_IO_read_end - fp->_IO_read_base - nread;
}
}
else
{
char *new_write_ptr = fp->_IO_write_ptr;
if (clen > 0)
offset += (fp->_wide_data->_IO_write_ptr
- fp->_wide_data->_IO_write_base) / clen;
else
{
enum __codecvt_result status = __codecvt_ok;
delta = (fp->_wide_data->_IO_write_ptr
- fp->_wide_data->_IO_write_base);
const wchar_t *write_base = fp->_wide_data->_IO_write_base;
/* FIXME: This actually ends up in two iterations of conversion,
one here and the next when the buffer actually gets flushed.
It may be possible to optimize this in future so that
wdo_write identifies already converted content and does not
redo it. In any case, this is much better than having to
flush buffers for every ftell. */
do
{
/* There is not enough space in the buffer to do the entire
conversion, so there is no point trying to avoid the
buffer flush. Just do it and go back to how it was with
the read mode. */
if (status == __codecvt_partial
|| (delta > 0 && new_write_ptr == fp->_IO_buf_end))
{
if (_IO_switch_to_wget_mode (fp))
return WEOF;
goto flushed;
}
const wchar_t *new_wbase = fp->_wide_data->_IO_write_base;
fp->_wide_data->_IO_state = fp->_wide_data->_IO_last_state;
status = (*cv->__codecvt_do_out) (cv,
&fp->_wide_data->_IO_state,
write_base,
write_base + delta,
&new_wbase,
new_write_ptr,
fp->_IO_buf_end,
&new_write_ptr);
delta -= new_wbase - write_base;
/* If there was an error, then return WEOF.
TODO: set buffer state. */
if (__builtin_expect (status == __codecvt_error, 0))
return WEOF;
}
while (delta > 0);
}
/* _IO_read_end coincides with fp._offset, so the actual file position
is fp._offset - (_IO_read_end - new_write_ptr). This is fine
even if fp._offset is not set, since fp->_IO_read_end is then at
_IO_buf_base and this adjustment is for unbuffered output. */
offset -= fp->_IO_read_end - new_write_ptr;
}
if (fp->_offset == _IO_pos_BAD)
{
if (mode != 0)
goto dumb;
else
{
result = _IO_SYSSEEK (fp, 0, dir);
if (result == EOF)
return result;
fp->_offset = result;
}
}
goto dumb;
/* Make offset absolute, assuming current pointer is file_ptr(). */
offset += fp->_offset;
@@ -802,10 +862,6 @@ _IO_wfile_seekoff (fp, offset, dir, mode)
}
/* At this point, dir==_IO_seek_set. */
/* If we are only interested in the current position we've found it now. */
if (mode == 0)
return offset;
/* If destination is within current buffer, optimize: */
if (fp->_offset != _IO_pos_BAD && fp->_IO_read_base != NULL
&& !_IO_in_backup (fp))
+61 -13
View File
@@ -17,6 +17,7 @@
<http://www.gnu.org/licenses/>. */
#include <assert.h>
#include <errno.h>
#include <locale.h>
#include <stdlib.h>
#include <string.h>
@@ -57,6 +58,45 @@ struct loaded_l10nfile *_nl_locale_file_list[__LC_LAST];
const char _nl_default_locale_path[] attribute_hidden = LOCALEDIR;
/* Checks if the name is actually present, that is, not NULL and not
empty. */
static inline int
name_present (const char *name)
{
return name != NULL && name[0] != '\0';
}
/* Checks that the locale name neither extremely long, nor contains a
".." path component (to prevent directory traversal). */
static inline int
valid_locale_name (const char *name)
{
/* Not set. */
size_t namelen = strlen (name);
/* Name too long. The limit is arbitrary and prevents stack overflow
issues later. */
if (__glibc_unlikely (namelen > 255))
return 0;
/* Directory traversal attempt. */
static const char slashdot[4] = {'/', '.', '.', '/'};
if (__glibc_unlikely (memmem (name, namelen,
slashdot, sizeof (slashdot)) != NULL))
return 0;
if (namelen == 2 && __glibc_unlikely (name[0] == '.' && name [1] == '.'))
return 0;
if (namelen >= 3
&& __glibc_unlikely (((name[0] == '.'
&& name[1] == '.'
&& name[2] == '/')
|| (name[namelen - 3] == '/'
&& name[namelen - 2] == '.'
&& name[namelen - 1] == '.'))))
return 0;
/* If there is a slash in the name, it must start with one. */
if (__glibc_unlikely (memchr (name, '/', namelen) != NULL) && name[0] != '/')
return 0;
return 1;
}
struct __locale_data *
internal_function
@@ -65,7 +105,7 @@ _nl_find_locale (const char *locale_path, size_t locale_path_len,
{
int mask;
/* Name of the locale for this category. */
char *loc_name;
char *loc_name = (char *) *name;
const char *language;
const char *modifier;
const char *territory;
@@ -73,31 +113,39 @@ _nl_find_locale (const char *locale_path, size_t locale_path_len,
const char *normalized_codeset;
struct loaded_l10nfile *locale_file;
if ((*name)[0] == '\0')
if (loc_name[0] == '\0')
{
/* The user decides which locale to use by setting environment
variables. */
*name = getenv ("LC_ALL");
if (*name == NULL || (*name)[0] == '\0')
*name = getenv (_nl_category_names.str
loc_name = getenv ("LC_ALL");
if (!name_present (loc_name))
loc_name = getenv (_nl_category_names.str
+ _nl_category_name_idxs[category]);
if (*name == NULL || (*name)[0] == '\0')
*name = getenv ("LANG");
if (!name_present (loc_name))
loc_name = getenv ("LANG");
if (!name_present (loc_name))
loc_name = (char *) _nl_C_name;
}
if (*name == NULL || (*name)[0] == '\0'
|| (__builtin_expect (__libc_enable_secure, 0)
&& strchr (*name, '/') != NULL))
*name = (char *) _nl_C_name;
/* We used to fall back to the C locale if the name contains a slash
character '/', but we now check for directory traversal in
valid_locale_name, so this is no longer necessary. */
if (__builtin_expect (strcmp (*name, _nl_C_name), 1) == 0
|| __builtin_expect (strcmp (*name, _nl_POSIX_name), 1) == 0)
if (__builtin_expect (strcmp (loc_name, _nl_C_name), 1) == 0
|| __builtin_expect (strcmp (loc_name, _nl_POSIX_name), 1) == 0)
{
/* We need not load anything. The needed data is contained in
the library itself. */
*name = (char *) _nl_C_name;
return _nl_C[category];
}
else if (!valid_locale_name (loc_name))
{
__set_errno (EINVAL);
return NULL;
}
*name = loc_name;
/* We really have to load some data. First we try the archive,
but only if there was no LOCPATH environment variable specified. */
+12 -4
View File
@@ -67,12 +67,20 @@ static const char *locnames[] =
#undef DEFINE_CATEGORY
};
/* Google local change: we've reduced the initial archive header
sizes, since we use very few of the entries. This saves ~100k.
The hash tables are sized larger than the number of entries we use.
The code will round their sizes up to the next power of 2, and if
it finds that they're >75% full will grow them as well. We set the
defaults to the size that we'll end up with given what we use.
The vectors are sized exactly to hold what we use. */
/* Size of the initial archive header. */
#define INITIAL_NUM_NAMES 900
#define INITIAL_SIZE_STRINGS 7500
#define INITIAL_NUM_LOCREC 420
#define INITIAL_NUM_SUMS 2000
#define INITIAL_NUM_NAMES 5 /* (hash table of structs) We use 3. */
#define INITIAL_SIZE_STRINGS 32 /* (vector of bytes) We use 32. */
#define INITIAL_NUM_LOCREC 2 /* (vector of structs) We use 2. */
#define INITIAL_NUM_SUMS 11 /* (hash table of structs) We use 6. */
/* Get and set values (possibly endian-swapped) in structures mapped
+12 -2
View File
@@ -272,6 +272,8 @@ setlocale (int category, const char *locale)
of entries of the form `CATEGORY=VALUE'. */
const char *newnames[__LC_LAST];
struct __locale_data *newdata[__LC_LAST];
/* Copy of the locale argument, for in-place splitting. */
char *locale_copy = NULL;
/* Set all name pointers to the argument name. */
for (category = 0; category < __LC_LAST; ++category)
@@ -281,7 +283,13 @@ setlocale (int category, const char *locale)
if (__builtin_expect (strchr (locale, ';') != NULL, 0))
{
/* This is a composite name. Make a copy and split it up. */
char *np = strdupa (locale);
locale_copy = strdup (locale);
if (__glibc_unlikely (locale_copy == NULL))
{
__libc_rwlock_unlock (__libc_setlocale_lock);
return NULL;
}
char *np = locale_copy;
char *cp;
int cnt;
@@ -299,6 +307,7 @@ setlocale (int category, const char *locale)
{
error_return:
__libc_rwlock_unlock (__libc_setlocale_lock);
free (locale_copy);
/* Bogus category name. */
ERROR_RETURN;
@@ -391,8 +400,9 @@ setlocale (int category, const char *locale)
/* Critical section left. */
__libc_rwlock_unlock (__libc_setlocale_lock);
/* Free the resources (the locale path variable). */
/* Free the resources. */
free (locale_path);
free (locale_copy);
return composite;
}
+9
View File
@@ -398,8 +398,17 @@ __malloc_assert (const char *assertion, const char *file, unsigned int line,
/* Definition for getting more memory from the OS. */
#if 0 /* Google-local: b/5732800: make calls go through PLT instead. */
#define MORECORE (*__morecore)
#define MORECORE_FAILURE 0
#else
#define __mmap mmap
#define __munmap munmap
#define __mremap mremap
#define __mprotect mprotect
#define MORECORE sbrk
#define MORECORE_FAILURE -1
#endif
void * __default_morecore (ptrdiff_t);
void *(*__morecore)(ptrdiff_t) = __default_morecore;
+1
View File
@@ -90,6 +90,7 @@ tests = test-matherr test-fenv atest-exp atest-sincos atest-exp2 basic-test \
test-misc test-fpucw test-fpucw-ieee tst-definitions test-tgmath \
test-tgmath-ret bug-nextafter bug-nexttoward bug-tgmath1 \
test-tgmath-int test-tgmath2 test-powl tst-CMPLX tst-CMPLX2 test-snan \
test-nan-overflow test-nan-payload \
test-fenv-tls $(tests-static)
tests-static = test-fpucw-static test-fpucw-ieee-static
# We do the `long double' tests only if this data type is available and
+2
View File
@@ -474,6 +474,7 @@ cos 0x1.0000010b239a9p0
cos 0x1.00000162a932bp0
cos 0x1.000002d452a10p0
cos 0x1.000005bc7d86dp0
cos 0x1.200145a975ce6p32
cos 1
cos 2
cos 3
@@ -1373,6 +1374,7 @@ sin 7
sin 8
sin 9
sin 10
sin 0x1.2001469775ce6p32
sincos 0
sincos -0
+138
View File
@@ -47298,6 +47298,75 @@ cos 0x1.000005bc7d86dp0
= cos tonearest ldbl-128ibm 0x1.000005bc7d86dp+0L : 0x8.a513ba9f703d3ffffffcb92354p-4L : inexact-ok
= cos towardzero ldbl-128ibm 0x1.000005bc7d86dp+0L : 0x8.a513ba9f703d3ffffffcb92354p-4L : inexact-ok
= cos upward ldbl-128ibm 0x1.000005bc7d86dp+0L : 0x8.a513ba9f703d3ffffffcb92358p-4L : inexact-ok
cos 0x1.200145a975ce6p32
= cos downward flt-32 0x1.200146p+32f : -0xf.74fbep-4f : inexact-ok
= cos tonearest flt-32 0x1.200146p+32f : -0xf.74fbdp-4f : inexact-ok
= cos towardzero flt-32 0x1.200146p+32f : -0xf.74fbdp-4f : inexact-ok
= cos upward flt-32 0x1.200146p+32f : -0xf.74fbdp-4f : inexact-ok
= cos downward dbl-64 0x1.200146p+32 : -0xf.74fbd5498fe5p-4 : inexact-ok
= cos tonearest dbl-64 0x1.200146p+32 : -0xf.74fbd5498fe5p-4 : inexact-ok
= cos towardzero dbl-64 0x1.200146p+32 : -0xf.74fbd5498fe48p-4 : inexact-ok
= cos upward dbl-64 0x1.200146p+32 : -0xf.74fbd5498fe48p-4 : inexact-ok
= cos downward ldbl-96-intel 0x1.200146p+32L : -0xf.74fbd5498fe4c0dp-4L : inexact-ok
= cos tonearest ldbl-96-intel 0x1.200146p+32L : -0xf.74fbd5498fe4c0cp-4L : inexact-ok
= cos towardzero ldbl-96-intel 0x1.200146p+32L : -0xf.74fbd5498fe4c0cp-4L : inexact-ok
= cos upward ldbl-96-intel 0x1.200146p+32L : -0xf.74fbd5498fe4c0cp-4L : inexact-ok
= cos downward ldbl-96-m68k 0x1.200146p+32L : -0xf.74fbd5498fe4c0dp-4L : inexact-ok
= cos tonearest ldbl-96-m68k 0x1.200146p+32L : -0xf.74fbd5498fe4c0cp-4L : inexact-ok
= cos towardzero ldbl-96-m68k 0x1.200146p+32L : -0xf.74fbd5498fe4c0cp-4L : inexact-ok
= cos upward ldbl-96-m68k 0x1.200146p+32L : -0xf.74fbd5498fe4c0cp-4L : inexact-ok
= cos downward ldbl-128 0x1.200146p+32L : -0xf.74fbd5498fe4c0c71bd9e4ef59e8p-4L : inexact-ok
= cos tonearest ldbl-128 0x1.200146p+32L : -0xf.74fbd5498fe4c0c71bd9e4ef59e8p-4L : inexact-ok
= cos towardzero ldbl-128 0x1.200146p+32L : -0xf.74fbd5498fe4c0c71bd9e4ef59ep-4L : inexact-ok
= cos upward ldbl-128 0x1.200146p+32L : -0xf.74fbd5498fe4c0c71bd9e4ef59ep-4L : inexact-ok
= cos downward ldbl-128ibm 0x1.200146p+32L : -0xf.74fbd5498fe4c0c71bd9e4ef5cp-4L : inexact-ok
= cos tonearest ldbl-128ibm 0x1.200146p+32L : -0xf.74fbd5498fe4c0c71bd9e4ef58p-4L : inexact-ok
= cos towardzero ldbl-128ibm 0x1.200146p+32L : -0xf.74fbd5498fe4c0c71bd9e4ef58p-4L : inexact-ok
= cos upward ldbl-128ibm 0x1.200146p+32L : -0xf.74fbd5498fe4c0c71bd9e4ef58p-4L : inexact-ok
= cos downward flt-32 0x1.200144p+32f : 0xf.bc96cp-4f : inexact-ok
= cos tonearest flt-32 0x1.200144p+32f : 0xf.bc96dp-4f : inexact-ok
= cos towardzero flt-32 0x1.200144p+32f : 0xf.bc96cp-4f : inexact-ok
= cos upward flt-32 0x1.200144p+32f : 0xf.bc96dp-4f : inexact-ok
= cos downward dbl-64 0x1.200144p+32 : 0xf.bc96ca2c658a8p-4 : inexact-ok
= cos tonearest dbl-64 0x1.200144p+32 : 0xf.bc96ca2c658a8p-4 : inexact-ok
= cos towardzero dbl-64 0x1.200144p+32 : 0xf.bc96ca2c658a8p-4 : inexact-ok
= cos upward dbl-64 0x1.200144p+32 : 0xf.bc96ca2c658bp-4 : inexact-ok
= cos downward ldbl-96-intel 0x1.200144p+32L : 0xf.bc96ca2c658abf5p-4L : inexact-ok
= cos tonearest ldbl-96-intel 0x1.200144p+32L : 0xf.bc96ca2c658abf6p-4L : inexact-ok
= cos towardzero ldbl-96-intel 0x1.200144p+32L : 0xf.bc96ca2c658abf5p-4L : inexact-ok
= cos upward ldbl-96-intel 0x1.200144p+32L : 0xf.bc96ca2c658abf6p-4L : inexact-ok
= cos downward ldbl-96-m68k 0x1.200144p+32L : 0xf.bc96ca2c658abf5p-4L : inexact-ok
= cos tonearest ldbl-96-m68k 0x1.200144p+32L : 0xf.bc96ca2c658abf6p-4L : inexact-ok
= cos towardzero ldbl-96-m68k 0x1.200144p+32L : 0xf.bc96ca2c658abf5p-4L : inexact-ok
= cos upward ldbl-96-m68k 0x1.200144p+32L : 0xf.bc96ca2c658abf6p-4L : inexact-ok
= cos downward ldbl-128 0x1.200144p+32L : 0xf.bc96ca2c658abf5ace7b886a8fbp-4L : inexact-ok
= cos tonearest ldbl-128 0x1.200144p+32L : 0xf.bc96ca2c658abf5ace7b886a8fbp-4L : inexact-ok
= cos towardzero ldbl-128 0x1.200144p+32L : 0xf.bc96ca2c658abf5ace7b886a8fbp-4L : inexact-ok
= cos upward ldbl-128 0x1.200144p+32L : 0xf.bc96ca2c658abf5ace7b886a8fb8p-4L : inexact-ok
= cos downward ldbl-128ibm 0x1.200144p+32L : 0xf.bc96ca2c658abf5ace7b886a8cp-4L : inexact-ok
= cos tonearest ldbl-128ibm 0x1.200144p+32L : 0xf.bc96ca2c658abf5ace7b886a9p-4L : inexact-ok
= cos towardzero ldbl-128ibm 0x1.200144p+32L : 0xf.bc96ca2c658abf5ace7b886a8cp-4L : inexact-ok
= cos upward ldbl-128ibm 0x1.200144p+32L : 0xf.bc96ca2c658abf5ace7b886a9p-4L : inexact-ok
= cos downward dbl-64 0x1.200145a975ce6p+32 : -0x6.568e7ed3dffdp-4 : inexact-ok
= cos tonearest dbl-64 0x1.200145a975ce6p+32 : -0x6.568e7ed3dffccp-4 : inexact-ok
= cos towardzero dbl-64 0x1.200145a975ce6p+32 : -0x6.568e7ed3dffccp-4 : inexact-ok
= cos upward dbl-64 0x1.200145a975ce6p+32 : -0x6.568e7ed3dffccp-4 : inexact-ok
= cos downward ldbl-96-intel 0x1.200145a975ce6p+32L : -0x6.568e7ed3dffcdfe8p-4L : inexact-ok
= cos tonearest ldbl-96-intel 0x1.200145a975ce6p+32L : -0x6.568e7ed3dffcdfep-4L : inexact-ok
= cos towardzero ldbl-96-intel 0x1.200145a975ce6p+32L : -0x6.568e7ed3dffcdfep-4L : inexact-ok
= cos upward ldbl-96-intel 0x1.200145a975ce6p+32L : -0x6.568e7ed3dffcdfep-4L : inexact-ok
= cos downward ldbl-96-m68k 0x1.200145a975ce6p+32L : -0x6.568e7ed3dffcdfe8p-4L : inexact-ok
= cos tonearest ldbl-96-m68k 0x1.200145a975ce6p+32L : -0x6.568e7ed3dffcdfep-4L : inexact-ok
= cos towardzero ldbl-96-m68k 0x1.200145a975ce6p+32L : -0x6.568e7ed3dffcdfep-4L : inexact-ok
= cos upward ldbl-96-m68k 0x1.200145a975ce6p+32L : -0x6.568e7ed3dffcdfep-4L : inexact-ok
= cos downward ldbl-128 0x1.200145a975ce6p+32L : -0x6.568e7ed3dffcdfe227fd726840e8p-4L : inexact-ok
= cos tonearest ldbl-128 0x1.200145a975ce6p+32L : -0x6.568e7ed3dffcdfe227fd726840e4p-4L : inexact-ok
= cos towardzero ldbl-128 0x1.200145a975ce6p+32L : -0x6.568e7ed3dffcdfe227fd726840e4p-4L : inexact-ok
= cos upward ldbl-128 0x1.200145a975ce6p+32L : -0x6.568e7ed3dffcdfe227fd726840e4p-4L : inexact-ok
= cos downward ldbl-128ibm 0x1.200145a975ce6p+32L : -0x6.568e7ed3dffcdfe227fd726842p-4L : inexact-ok
= cos tonearest ldbl-128ibm 0x1.200145a975ce6p+32L : -0x6.568e7ed3dffcdfe227fd72684p-4L : inexact-ok
= cos towardzero ldbl-128ibm 0x1.200145a975ce6p+32L : -0x6.568e7ed3dffcdfe227fd72684p-4L : inexact-ok
= cos upward ldbl-128ibm 0x1.200145a975ce6p+32L : -0x6.568e7ed3dffcdfe227fd72684p-4L : inexact-ok
cos 1
= cos downward flt-32 0x1p+0f : 0x8.a514p-4f : inexact-ok
= cos tonearest flt-32 0x1p+0f : 0x8.a514p-4f : inexact-ok
@@ -115514,6 +115583,75 @@ sin 10
= sin tonearest ldbl-128ibm 0xap+0L : -0x8.b44f7af9a7a92ce7fb22be025p-4L : inexact-ok
= sin towardzero ldbl-128ibm 0xap+0L : -0x8.b44f7af9a7a92ce7fb22be024cp-4L : inexact-ok
= sin upward ldbl-128ibm 0xap+0L : -0x8.b44f7af9a7a92ce7fb22be024cp-4L : inexact-ok
sin 0x1.2001469775ce6p32
= sin downward flt-32 0x1.200148p+32f : -0x5.595d8p-4f : inexact-ok
= sin tonearest flt-32 0x1.200148p+32f : -0x5.595d8p-4f : inexact-ok
= sin towardzero flt-32 0x1.200148p+32f : -0x5.595d78p-4f : inexact-ok
= sin upward flt-32 0x1.200148p+32f : -0x5.595d78p-4f : inexact-ok
= sin downward dbl-64 0x1.200148p+32 : -0x5.595d7e536fe38p-4 : inexact-ok
= sin tonearest dbl-64 0x1.200148p+32 : -0x5.595d7e536fe34p-4 : inexact-ok
= sin towardzero dbl-64 0x1.200148p+32 : -0x5.595d7e536fe34p-4 : inexact-ok
= sin upward dbl-64 0x1.200148p+32 : -0x5.595d7e536fe34p-4 : inexact-ok
= sin downward ldbl-96-intel 0x1.200148p+32L : -0x5.595d7e536fe35eep-4L : inexact-ok
= sin tonearest ldbl-96-intel 0x1.200148p+32L : -0x5.595d7e536fe35ed8p-4L : inexact-ok
= sin towardzero ldbl-96-intel 0x1.200148p+32L : -0x5.595d7e536fe35ed8p-4L : inexact-ok
= sin upward ldbl-96-intel 0x1.200148p+32L : -0x5.595d7e536fe35ed8p-4L : inexact-ok
= sin downward ldbl-96-m68k 0x1.200148p+32L : -0x5.595d7e536fe35eep-4L : inexact-ok
= sin tonearest ldbl-96-m68k 0x1.200148p+32L : -0x5.595d7e536fe35ed8p-4L : inexact-ok
= sin towardzero ldbl-96-m68k 0x1.200148p+32L : -0x5.595d7e536fe35ed8p-4L : inexact-ok
= sin upward ldbl-96-m68k 0x1.200148p+32L : -0x5.595d7e536fe35ed8p-4L : inexact-ok
= sin downward ldbl-128 0x1.200148p+32L : -0x5.595d7e536fe35edbe2ad0df9d944p-4L : inexact-ok
= sin tonearest ldbl-128 0x1.200148p+32L : -0x5.595d7e536fe35edbe2ad0df9d94p-4L : inexact-ok
= sin towardzero ldbl-128 0x1.200148p+32L : -0x5.595d7e536fe35edbe2ad0df9d94p-4L : inexact-ok
= sin upward ldbl-128 0x1.200148p+32L : -0x5.595d7e536fe35edbe2ad0df9d94p-4L : inexact-ok
= sin downward ldbl-128ibm 0x1.200148p+32L : -0x5.595d7e536fe35edbe2ad0df9dap-4L : inexact-ok
= sin tonearest ldbl-128ibm 0x1.200148p+32L : -0x5.595d7e536fe35edbe2ad0df9dap-4L : inexact-ok
= sin towardzero ldbl-128ibm 0x1.200148p+32L : -0x5.595d7e536fe35edbe2ad0df9d8p-4L : inexact-ok
= sin upward ldbl-128ibm 0x1.200148p+32L : -0x5.595d7e536fe35edbe2ad0df9d8p-4L : inexact-ok
= sin downward flt-32 0x1.200146p+32f : 0x4.220ffp-4f : inexact-ok
= sin tonearest flt-32 0x1.200146p+32f : 0x4.220ffp-4f : inexact-ok
= sin towardzero flt-32 0x1.200146p+32f : 0x4.220ffp-4f : inexact-ok
= sin upward flt-32 0x1.200146p+32f : 0x4.220ff8p-4f : inexact-ok
= sin downward dbl-64 0x1.200146p+32 : 0x4.220ff25f5cfp-4 : inexact-ok
= sin tonearest dbl-64 0x1.200146p+32 : 0x4.220ff25f5cf04p-4 : inexact-ok
= sin towardzero dbl-64 0x1.200146p+32 : 0x4.220ff25f5cfp-4 : inexact-ok
= sin upward dbl-64 0x1.200146p+32 : 0x4.220ff25f5cf04p-4 : inexact-ok
= sin downward ldbl-96-intel 0x1.200146p+32L : 0x4.220ff25f5cf02a4p-4L : inexact-ok
= sin tonearest ldbl-96-intel 0x1.200146p+32L : 0x4.220ff25f5cf02a48p-4L : inexact-ok
= sin towardzero ldbl-96-intel 0x1.200146p+32L : 0x4.220ff25f5cf02a4p-4L : inexact-ok
= sin upward ldbl-96-intel 0x1.200146p+32L : 0x4.220ff25f5cf02a48p-4L : inexact-ok
= sin downward ldbl-96-m68k 0x1.200146p+32L : 0x4.220ff25f5cf02a4p-4L : inexact-ok
= sin tonearest ldbl-96-m68k 0x1.200146p+32L : 0x4.220ff25f5cf02a48p-4L : inexact-ok
= sin towardzero ldbl-96-m68k 0x1.200146p+32L : 0x4.220ff25f5cf02a4p-4L : inexact-ok
= sin upward ldbl-96-m68k 0x1.200146p+32L : 0x4.220ff25f5cf02a48p-4L : inexact-ok
= sin downward ldbl-128 0x1.200146p+32L : 0x4.220ff25f5cf02a464dbb3a679ccp-4L : inexact-ok
= sin tonearest ldbl-128 0x1.200146p+32L : 0x4.220ff25f5cf02a464dbb3a679ccp-4L : inexact-ok
= sin towardzero ldbl-128 0x1.200146p+32L : 0x4.220ff25f5cf02a464dbb3a679ccp-4L : inexact-ok
= sin upward ldbl-128 0x1.200146p+32L : 0x4.220ff25f5cf02a464dbb3a679cc4p-4L : inexact-ok
= sin downward ldbl-128ibm 0x1.200146p+32L : 0x4.220ff25f5cf02a464dbb3a679cp-4L : inexact-ok
= sin tonearest ldbl-128ibm 0x1.200146p+32L : 0x4.220ff25f5cf02a464dbb3a679cp-4L : inexact-ok
= sin towardzero ldbl-128ibm 0x1.200146p+32L : 0x4.220ff25f5cf02a464dbb3a679cp-4L : inexact-ok
= sin upward ldbl-128ibm 0x1.200146p+32L : 0x4.220ff25f5cf02a464dbb3a679ep-4L : inexact-ok
= sin downward dbl-64 0x1.2001469775ce6p+32 : -0x6.444fda50019fcp-4 : inexact-ok
= sin tonearest dbl-64 0x1.2001469775ce6p+32 : -0x6.444fda50019f8p-4 : inexact-ok
= sin towardzero dbl-64 0x1.2001469775ce6p+32 : -0x6.444fda50019f8p-4 : inexact-ok
= sin upward dbl-64 0x1.2001469775ce6p+32 : -0x6.444fda50019f8p-4 : inexact-ok
= sin downward ldbl-96-intel 0x1.2001469775ce6p+32L : -0x6.444fda50019f9f6p-4L : inexact-ok
= sin tonearest ldbl-96-intel 0x1.2001469775ce6p+32L : -0x6.444fda50019f9f58p-4L : inexact-ok
= sin towardzero ldbl-96-intel 0x1.2001469775ce6p+32L : -0x6.444fda50019f9f58p-4L : inexact-ok
= sin upward ldbl-96-intel 0x1.2001469775ce6p+32L : -0x6.444fda50019f9f58p-4L : inexact-ok
= sin downward ldbl-96-m68k 0x1.2001469775ce6p+32L : -0x6.444fda50019f9f6p-4L : inexact-ok
= sin tonearest ldbl-96-m68k 0x1.2001469775ce6p+32L : -0x6.444fda50019f9f58p-4L : inexact-ok
= sin towardzero ldbl-96-m68k 0x1.2001469775ce6p+32L : -0x6.444fda50019f9f58p-4L : inexact-ok
= sin upward ldbl-96-m68k 0x1.2001469775ce6p+32L : -0x6.444fda50019f9f58p-4L : inexact-ok
= sin downward ldbl-128 0x1.2001469775ce6p+32L : -0x6.444fda50019f9f5ba3779ca70604p-4L : inexact-ok
= sin tonearest ldbl-128 0x1.2001469775ce6p+32L : -0x6.444fda50019f9f5ba3779ca706p-4L : inexact-ok
= sin towardzero ldbl-128 0x1.2001469775ce6p+32L : -0x6.444fda50019f9f5ba3779ca706p-4L : inexact-ok
= sin upward ldbl-128 0x1.2001469775ce6p+32L : -0x6.444fda50019f9f5ba3779ca706p-4L : inexact-ok
= sin downward ldbl-128ibm 0x1.2001469775ce6p+32L : -0x6.444fda50019f9f5ba3779ca708p-4L : inexact-ok
= sin tonearest ldbl-128ibm 0x1.2001469775ce6p+32L : -0x6.444fda50019f9f5ba3779ca706p-4L : inexact-ok
= sin towardzero ldbl-128ibm 0x1.2001469775ce6p+32L : -0x6.444fda50019f9f5ba3779ca706p-4L : inexact-ok
= sin upward ldbl-128ibm 0x1.2001469775ce6p+32L : -0x6.444fda50019f9f5ba3779ca706p-4L : inexact-ok
sincos 0
= sincos downward flt-32 0x0p+0f : 0x0p+0f 0x1p+0f : inexact-ok
= sincos tonearest flt-32 0x0p+0f : 0x0p+0f 0x1p+0f : inexact-ok
+1
View File
@@ -150,6 +150,7 @@ __END_NAMESPACE_C99
_Mdouble_BEGIN_NAMESPACE
/* Return X to the Y power. */
__attribute_noplt__
__MATHCALL (pow,, (_Mdouble_ __x, _Mdouble_ __y));
/* Return the square root of X. */
+53
View File
@@ -6000,6 +6000,15 @@ static const struct test_f_f_data ceil_test_data[] =
TEST_f_f (ceil, -72057594037927936.75L, -72057594037927936.0L),
TEST_f_f (ceil, -72057594037927937.5L, -72057594037927937.0L),
/* Check cases where first double is a exact integer higher than 2^52 and
the precision is determined by second long double for IBM long double. */
TEST_f_f (ceil, 34503599627370498.515625L, 34503599627370499.0L),
TEST_f_f (ceil, -34503599627370498.515625L, -34503599627370498.0L),
# if LDBL_MANT_DIG >= 106
TEST_f_f (ceil, 1192568192774434123539907640624.484375L, 1192568192774434123539907640625.0L),
TEST_f_f (ceil, -1192568192774434123539907640624.484375L, -1192568192774434123539907640624.0L),
# endif
TEST_f_f (ceil, 10141204801825835211973625643007.5L, 10141204801825835211973625643008.0L),
TEST_f_f (ceil, 10141204801825835211973625643008.25L, 10141204801825835211973625643009.0L),
TEST_f_f (ceil, 10141204801825835211973625643008.5L, 10141204801825835211973625643009.0L),
@@ -8714,6 +8723,15 @@ static const struct test_f_f1_data frexp_test_data[] =
TEST_fI_f1 (frexp, 12.8L, 0.8L, 4, NO_INEXACT_EXCEPTION),
TEST_fI_f1 (frexp, -27.34L, -0.854375L, 5, NO_INEXACT_EXCEPTION),
#if defined TEST_LDOUBLE && LDBL_MANT_DIG >= 106
TEST_fI_f1 (frexp, 1.0L-0x1p-106L, 1.0L-0x1p-106L, 0, NO_INEXACT_EXCEPTION),
TEST_fI_f1 (frexp, 1.0L, 0.5L, 1, NO_INEXACT_EXCEPTION),
TEST_fI_f1 (frexp, 1.0L+0x1p-105L, 0.5L+0x1p-106L, 1, NO_INEXACT_EXCEPTION),
TEST_fI_f1 (frexp, -1.0L+0x1p-106L, -1.0L+0x1p-106L, 0, NO_INEXACT_EXCEPTION),
TEST_fI_f1 (frexp, -1.0L, -0.5L, 1, NO_INEXACT_EXCEPTION),
TEST_fI_f1 (frexp, -1.0L-0x1p-105L, -0.5L-0x1p-106L, 1, NO_INEXACT_EXCEPTION),
#endif
};
static void
@@ -10494,6 +10512,20 @@ static const struct test_f_f_data nearbyint_test_data[] =
TEST_f_f (nearbyint, -281474976710656.75, -281474976710657.0, NO_INEXACT_EXCEPTION),
TEST_f_f (nearbyint, -562949953421312.75, -562949953421313.0, NO_INEXACT_EXCEPTION),
TEST_f_f (nearbyint, -1125899906842624.75, -1125899906842625.0, NO_INEXACT_EXCEPTION),
#endif
#ifdef TEST_LDOUBLE
/* Check cases where first double is a exact integer higher than 2^52 and
the precision is determined by second long double for IBM long double. */
TEST_f_f (nearbyint, 34503599627370498.515625L, 34503599627370499.0L),
TEST_f_f (nearbyint, -34503599627370498.515625L, -34503599627370499.0L),
# if LDBL_MANT_DIG >= 106
TEST_f_f (nearbyint, 1024.5000000000001L, 1025.0L, NO_INEXACT_EXCEPTION),
TEST_f_f (nearbyint, 1025.5000000000001L, 1026.0L, NO_INEXACT_EXCEPTION),
TEST_f_f (nearbyint, -1024.5000000000001L, -1025.0L, NO_INEXACT_EXCEPTION),
TEST_f_f (nearbyint, -1025.5000000000001L, -1026.0L, NO_INEXACT_EXCEPTION),
TEST_f_f (nearbyint, 1192568192774434123539907640624.484375L, 1192568192774434123539907640624.0L),
TEST_f_f (nearbyint, -1192568192774434123539907640624.484375L, -1192568192774434123539907640624.0L),
# endif
#endif
};
@@ -10528,6 +10560,14 @@ static const struct test_ff_f_data nextafter_test_data[] =
// XXX Enable once gcc is fixed.
//TEST_ff_f (nextafter, 0x0.00000040000000000000p-16385L, -0.1L, 0x0.0000003ffffffff00000p-16385L),
#endif
#if defined TEST_LDOUBLE && LDBL_MANT_DIG == 106
TEST_ff_f (nextafter, 1.0L, -10.0L, 1.0L-0x1p-106L, NO_EXCEPTION),
TEST_ff_f (nextafter, 1.0L, 10.0L, 1.0L+0x1p-105L, NO_EXCEPTION),
TEST_ff_f (nextafter, 1.0L-0x1p-106L, 10.0L, 1.0L, NO_EXCEPTION),
TEST_ff_f (nextafter, -1.0L, -10.0L, -1.0L-0x1p-105L, NO_EXCEPTION),
TEST_ff_f (nextafter, -1.0L, 10.0L, -1.0L+0x1p-106L, NO_EXCEPTION),
TEST_ff_f (nextafter, -1.0L+0x1p-106L, -10.0L, -1.0L, NO_EXCEPTION),
#endif
/* XXX We need the hexadecimal FP number representation here for further
tests. */
@@ -11299,6 +11339,10 @@ static const struct test_f_f_data rint_test_data[] =
TEST_f_f (rint, 4503599627370497.5L, 4503599627370498.0L, INEXACT_EXCEPTION),
# if LDBL_MANT_DIG > 100
TEST_f_f (rint, 1024.5000000000001L, 1025.0L, INEXACT_EXCEPTION),
TEST_f_f (rint, 1025.5000000000001L, 1026.0L, INEXACT_EXCEPTION),
TEST_f_f (rint, -1024.5000000000001L, -1025.0L, INEXACT_EXCEPTION),
TEST_f_f (rint, -1025.5000000000001L, -1026.0L, INEXACT_EXCEPTION),
TEST_f_f (rint, 4503599627370494.5000000000001L, 4503599627370495.0L, INEXACT_EXCEPTION),
TEST_f_f (rint, 4503599627370495.5000000000001L, 4503599627370496.0L, INEXACT_EXCEPTION),
TEST_f_f (rint, 4503599627370496.5000000000001L, 4503599627370497.0L, INEXACT_EXCEPTION),
@@ -11784,6 +11828,15 @@ static const struct test_f_f_data round_test_data[] =
TEST_f_f (round, -72057594037927936.75L, -72057594037927937.0L),
TEST_f_f (round, -72057594037927937.5L, -72057594037927938.0L),
/* Check cases where first double is a exact integer higher than 2^52 and
the precision is determined by second long double for IBM long double. */
TEST_f_f (round, 34503599627370498.515625L, 34503599627370499.0L),
TEST_f_f (round, -34503599627370498.515625L, -34503599627370499.0L),
# if LDBL_MANT_DIG >= 106
TEST_f_f (round, 1192568192774434123539907640624.484375L, 1192568192774434123539907640624.0L),
TEST_f_f (round, -1192568192774434123539907640624.484375L, -1192568192774434123539907640624.0L),
# endif
TEST_f_f (round, 10141204801825835211973625643007.5L, 10141204801825835211973625643008.0L),
TEST_f_f (round, 10141204801825835211973625643008.25L, 10141204801825835211973625643008.0L),
TEST_f_f (round, 10141204801825835211973625643008.5L, 10141204801825835211973625643009.0L),
+1 -8
View File
@@ -28,14 +28,7 @@
double
__nan (const char *tagp)
{
if (tagp[0] != '\0')
{
char buf[6 + strlen (tagp)];
sprintf (buf, "NAN(%s)", tagp);
return strtod (buf, NULL);
}
return NAN;
return __strtod_nan (tagp, NULL, 0);
}
weak_alias (__nan, nan)
#ifdef NO_LONG_DOUBLE
+1 -8
View File
@@ -28,13 +28,6 @@
float
__nanf (const char *tagp)
{
if (tagp[0] != '\0')
{
char buf[6 + strlen (tagp)];
sprintf (buf, "NAN(%s)", tagp);
return strtof (buf, NULL);
}
return NAN;
return __strtof_nan (tagp, NULL, 0);
}
weak_alias (__nanf, nanf)
+1 -8
View File
@@ -28,13 +28,6 @@
long double
__nanl (const char *tagp)
{
if (tagp[0] != '\0')
{
char buf[6 + strlen (tagp)];
sprintf (buf, "NAN(%s)", tagp);
return strtold (buf, NULL);
}
return NAN;
return __strtold_nan (tagp, NULL, 0);
}
weak_alias (__nanl, nanl)
+66
View File
@@ -0,0 +1,66 @@
/* Test nan functions stack overflow (bug 16962).
Copyright (C) 2015 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <sys/resource.h>
#define STACK_LIM 1048576
#define STRING_SIZE (2 * STACK_LIM)
static int
do_test (void)
{
int result = 0;
struct rlimit lim;
getrlimit (RLIMIT_STACK, &lim);
lim.rlim_cur = STACK_LIM;
setrlimit (RLIMIT_STACK, &lim);
char *nanstr = malloc (STRING_SIZE);
if (nanstr == NULL)
{
puts ("malloc failed, cannot test");
return 77;
}
memset (nanstr, '0', STRING_SIZE - 1);
nanstr[STRING_SIZE - 1] = 0;
#define NAN_TEST(TYPE, FUNC) \
do \
{ \
char *volatile p = nanstr; \
volatile TYPE v = FUNC (p); \
if (isnan (v)) \
puts ("PASS: " #FUNC); \
else \
{ \
puts ("FAIL: " #FUNC); \
result = 1; \
} \
} \
while (0)
NAN_TEST (float, nanf);
NAN_TEST (double, nan);
#ifndef NO_LONG_DOUBLE
NAN_TEST (long double, nanl);
#endif
return result;
}
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"
+122
View File
@@ -0,0 +1,122 @@
/* Test nan functions payload handling (bug 16961).
Copyright (C) 2015 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <float.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* Avoid built-in functions. */
#define WRAP_NAN(FUNC, STR) \
({ const char *volatile wns = (STR); FUNC (wns); })
#define WRAP_STRTO(FUNC, STR) \
({ const char *volatile wss = (STR); FUNC (wss, NULL); })
#define CHECK_IS_NAN(TYPE, A) \
do \
{ \
if (isnan (A)) \
puts ("PASS: " #TYPE " " #A); \
else \
{ \
puts ("FAIL: " #TYPE " " #A); \
result = 1; \
} \
} \
while (0)
#define CHECK_SAME_NAN(TYPE, A, B) \
do \
{ \
if (memcmp (&(A), &(B), sizeof (A)) == 0) \
puts ("PASS: " #TYPE " " #A " = " #B); \
else \
{ \
puts ("FAIL: " #TYPE " " #A " = " #B); \
result = 1; \
} \
} \
while (0)
#define CHECK_DIFF_NAN(TYPE, A, B) \
do \
{ \
if (memcmp (&(A), &(B), sizeof (A)) != 0) \
puts ("PASS: " #TYPE " " #A " != " #B); \
else \
{ \
puts ("FAIL: " #TYPE " " #A " != " #B); \
result = 1; \
} \
} \
while (0)
/* Cannot test payloads by memcmp for formats where NaNs have padding
bits. */
#define CAN_TEST_EQ(MANT_DIG) ((MANT_DIG) != 64 && (MANT_DIG) != 106)
#define RUN_TESTS(TYPE, SFUNC, FUNC, MANT_DIG) \
do \
{ \
TYPE n123 = WRAP_NAN (FUNC, "123"); \
CHECK_IS_NAN (TYPE, n123); \
TYPE s123 = WRAP_STRTO (SFUNC, "NAN(123)"); \
CHECK_IS_NAN (TYPE, s123); \
TYPE n456 = WRAP_NAN (FUNC, "456"); \
CHECK_IS_NAN (TYPE, n456); \
TYPE s456 = WRAP_STRTO (SFUNC, "NAN(456)"); \
CHECK_IS_NAN (TYPE, s456); \
TYPE n123x = WRAP_NAN (FUNC, "123)"); \
CHECK_IS_NAN (TYPE, n123x); \
TYPE nemp = WRAP_NAN (FUNC, ""); \
CHECK_IS_NAN (TYPE, nemp); \
TYPE semp = WRAP_STRTO (SFUNC, "NAN()"); \
CHECK_IS_NAN (TYPE, semp); \
TYPE sx = WRAP_STRTO (SFUNC, "NAN"); \
CHECK_IS_NAN (TYPE, sx); \
if (CAN_TEST_EQ (MANT_DIG)) \
CHECK_SAME_NAN (TYPE, n123, s123); \
if (CAN_TEST_EQ (MANT_DIG)) \
CHECK_SAME_NAN (TYPE, n456, s456); \
if (CAN_TEST_EQ (MANT_DIG)) \
CHECK_SAME_NAN (TYPE, nemp, semp); \
if (CAN_TEST_EQ (MANT_DIG)) \
CHECK_SAME_NAN (TYPE, n123x, sx); \
CHECK_DIFF_NAN (TYPE, n123, n456); \
CHECK_DIFF_NAN (TYPE, n123, nemp); \
CHECK_DIFF_NAN (TYPE, n123, n123x); \
CHECK_DIFF_NAN (TYPE, n456, nemp); \
CHECK_DIFF_NAN (TYPE, n456, n123x); \
} \
while (0)
static int
do_test (void)
{
int result = 0;
RUN_TESTS (float, strtof, nanf, FLT_MANT_DIG);
RUN_TESTS (double, strtod, nan, DBL_MANT_DIG);
#ifndef NO_LONG_DOUBLE
RUN_TESTS (long double, strtold, nanl, LDBL_MANT_DIG);
#endif
return result;
}
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"
+2 -1
View File
@@ -76,7 +76,8 @@ install-lib := libg.a
gpl2lgpl := error.c error.h
tests := tst-dirname tst-tsearch tst-fdset tst-efgcvt tst-mntent tst-hsearch \
tst-error1 tst-pselect tst-insremque tst-mntent2 bug-hsearch1
tst-error1 tst-pselect tst-insremque tst-mntent2 bug-hsearch1 \
bug18240
ifeq ($(run-built-tests),yes)
tests: $(objpfx)tst-error1-mem
endif
+97
View File
@@ -0,0 +1,97 @@
/* Test integer wraparound in hcreate.
Copyright (C) 2016-2017 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <errno.h>
#include <limits.h>
#include <search.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/resource.h>
static void
test_size (size_t size)
{
int res = hcreate (size);
if (res == 0)
{
if (errno == ENOMEM)
return;
printf ("error: hcreate (%zu): %m\n", size);
exit (1);
}
char *keys[100];
for (int i = 0; i < 100; ++i)
{
if (asprintf (keys + i, "%d", i) < 0)
{
printf ("error: asprintf: %m\n");
exit (1);
}
ENTRY e = { keys[i], (char *) "value" };
if (hsearch (e, ENTER) == NULL)
{
printf ("error: hsearch (\"%s\"): %m\n", keys[i]);
exit (1);
}
}
hdestroy ();
for (int i = 0; i < 100; ++i)
free (keys[i]);
}
static int
do_test (void)
{
/* Limit the size of the process, so that memory allocation will
fail without impacting the entire system. */
{
struct rlimit limit;
if (getrlimit (RLIMIT_AS, &limit) != 0)
{
printf ("getrlimit (RLIMIT_AS) failed: %m\n");
return 1;
}
long target = 100 * 1024 * 1024;
if (limit.rlim_cur == RLIM_INFINITY || limit.rlim_cur > target)
{
limit.rlim_cur = target;
if (setrlimit (RLIMIT_AS, &limit) != 0)
{
printf ("setrlimit (RLIMIT_AS) failed: %m\n");
return 1;
}
}
}
test_size (500);
test_size (-1);
test_size (-3);
test_size (INT_MAX - 2);
test_size (INT_MAX - 1);
test_size (INT_MAX);
test_size (((unsigned) INT_MAX) + 1);
test_size (UINT_MAX - 2);
test_size (UINT_MAX - 1);
test_size (UINT_MAX);
return 0;
}
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"
+18 -12
View File
@@ -19,7 +19,7 @@
#include <errno.h>
#include <malloc.h>
#include <string.h>
#include <stdint.h>
#include <search.h>
/* [Aho,Sethi,Ullman] Compilers: Principles, Techniques and Tools, 1986
@@ -46,15 +46,12 @@ static int
isprime (unsigned int number)
{
/* no even number will be passed */
unsigned int div = 3;
while (div * div < number && number % div != 0)
div += 2;
return number % div != 0;
for (unsigned int div = 3; div <= number / div; div += 2)
if (number % div == 0)
return 0;
return 1;
}
/* Before using the hash table we must allocate memory for it.
Test for an existing table are done. We allocate one element
more as the found prime number says. This is done for more effective
@@ -81,10 +78,19 @@ hcreate_r (nel, htab)
use will not work. */
if (nel < 3)
nel = 3;
/* Change nel to the first prime number not smaller as nel. */
nel |= 1; /* make odd */
while (!isprime (nel))
nel += 2;
/* Change nel to the first prime number in the range [nel, UINT_MAX - 2],
The '- 2' means 'nel += 2' cannot overflow. */
for (nel |= 1; ; nel += 2)
{
if (UINT_MAX - 2 < nel)
{
__set_errno (ENOMEM);
return 0;
}
if (isprime (nel))
break;
}
htab->size = nel;
htab->filled = 0;
+2
View File
@@ -33,4 +33,6 @@ __mktemp (template)
}
weak_alias (__mktemp, mktemp)
#if 0 /* Google-local: b/6115789 */
link_warning (mktemp, "the use of `mktemp' is dangerous, better use `mkstemp'")
#endif
+16
View File
@@ -232,6 +232,15 @@
# define __attribute_pure__ /* Ignore */
#endif
/* GCC 4.9 onwards supports function attribute "noplt". Calls to functions
declared with this attribute avoid the PLT and call them indirectly via
a GOT entry. */
#if __GNUC_PREREQ (4,9) && defined(__GOOGLE_GLIBC_NOPLT)
# define __attribute_noplt__ __attribute__ ((noplt))
#else
# define __attribute_noplt__ /* Ignore */
#endif
/* This declaration tells the compiler that the value is constant. */
#if __GNUC_PREREQ (2,5)
# define __attribute_const__ __attribute__ ((__const__))
@@ -303,6 +312,13 @@
# define __wur /* Ignore */
#endif
/* Google specific: Disable __warn_unused_result__ attribute even if
_FORTIFY_SOURCE is specified. Not all google3 code compiles when it's set */
#ifdef _GOOGLE_FORTIFY_SOURCE_NO_WARN_UNUSED_RESULT
# undef __wur
# define __wur /* Ignore */
#endif
/* Forces a function to be always inlined. */
#if __GNUC_PREREQ (3,2)
# define __always_inline __inline __attribute__ ((__always_inline__))
+5 -2
View File
@@ -34,9 +34,12 @@ databases = proto service hosts network grp pwd rpc ethers \
spwd netgrp alias publickey
# Specify rules for the nss_* modules.
services := nis nisplus compat
extra-libs = libnsl $(services:%=libnss_%)
# Google-local: Disable NIS.
# services := nis nisplus compat
#
# extra-libs = libnsl $(services:%=libnss_%)
# These libraries will be built in the `others' pass rather than
# the `lib' pass, because they depend on libc.so being built already.
extra-libs-others = $(extra-libs)
+31 -9
View File
@@ -137,6 +137,10 @@ libpthread-static-only-routines = pthread_atfork
CFLAGS-pthread_atfork.c = -DNOT_IN_libc
# Google-local (b/14616463): Turn off function sections in events.c to
# avoid folding that causes a bad debugging experience.
CFLAGS-events.c = -fno-function-sections
# Since cancellation handling is in large parts handled using exceptions
# we have to compile some files with exception handling enabled, some
# even with asynchronous unwind tables.
@@ -170,8 +174,10 @@ CFLAGS-forward.c = -fexceptions
# block and therefore temporarily enable asynchronous cancellation.
# Those must be compiled asynchronous unwind tables.
CFLAGS-pthread_testcancel.c = -fexceptions
CFLAGS-pthread_join.c = -fexceptions -fasynchronous-unwind-tables
CFLAGS-pthread_timedjoin.c = -fexceptions -fasynchronous-unwind-tables
CFLAGS-pthread_join.c = -fexceptions -fasynchronous-unwind-tables \
-fno-omit-frame-pointer
CFLAGS-pthread_timedjoin.c = -fexceptions -fasynchronous-unwind-tables \
-fno-omit-frame-pointer
CFLAGS-pthread_once.c = $(uses-callbacks) -fexceptions \
-fasynchronous-unwind-tables
CFLAGS-pthread_cond_wait.c = -fexceptions -fasynchronous-unwind-tables
@@ -222,13 +228,13 @@ tests = tst-typesizes \
tst-rwlock5 tst-rwlock6 tst-rwlock7 tst-rwlock8 tst-rwlock9 \
tst-rwlock10 tst-rwlock11 tst-rwlock12 tst-rwlock13 tst-rwlock14 \
tst-once1 tst-once2 tst-once3 tst-once4 \
tst-key1 tst-key2 tst-key3 tst-key4 \
tst-key1 tst-key2 tst-key3 tst-key4 tst-key5 \
tst-sem1 tst-sem2 tst-sem3 tst-sem4 tst-sem5 tst-sem6 tst-sem7 \
tst-sem8 tst-sem9 tst-sem10 tst-sem11 tst-sem12 tst-sem13 tst-sem14 \
tst-barrier1 tst-barrier2 tst-barrier3 tst-barrier4 \
tst-align tst-align2 tst-align3 \
tst-basic1 tst-basic2 tst-basic3 tst-basic4 tst-basic5 tst-basic6 \
tst-basic7 \
tst-basic7 tst-basic8 \
tst-kill1 tst-kill2 tst-kill3 tst-kill4 tst-kill5 tst-kill6 \
tst-raise1 \
tst-join1 tst-join2 tst-join3 tst-join4 tst-join5 tst-join6 \
@@ -293,8 +299,8 @@ tests += tst-cancelx2 tst-cancelx3 tst-cancelx4 tst-cancelx5 \
tst-oncex3 tst-oncex4
endif
ifeq ($(build-shared),yes)
tests += tst-atfork2 tst-tls3 tst-tls4 tst-tls5 tst-_res1 tst-fini1 \
tst-stackguard1
tests += tst-atfork2 tst-tls3 tst-tls4 tst-tls5 tst-tls7 tst-_res1 tst-fini1 \
tst-stackguard1 tst-tls77
tests-nolibpthread += tst-fini1
ifeq ($(have-z-execstack),yes)
tests += tst-execstack
@@ -304,7 +310,8 @@ endif
modules-names = tst-atfork2mod tst-tls3mod tst-tls4moda tst-tls4modb \
tst-tls5mod tst-tls5moda tst-tls5modb tst-tls5modc \
tst-tls5modd tst-tls5mode tst-tls5modf \
tst-_res1mod1 tst-_res1mod2 tst-execstack-mod tst-fini1mod
tst-_res1mod1 tst-_res1mod2 tst-execstack-mod tst-fini1mod \
tst-tls7mod tst-tls77mod
extra-test-objs += $(addsuffix .os,$(strip $(modules-names))) tst-cleanup4aux.o
test-extras += $(modules-names) tst-cleanup4aux
test-modules = $(addprefix $(objpfx),$(addsuffix .so,$(modules-names)))
@@ -318,6 +325,8 @@ tst-tls5modc.so-no-z-defs = yes
tst-tls5modd.so-no-z-defs = yes
tst-tls5mode.so-no-z-defs = yes
tst-tls5modf.so-no-z-defs = yes
tst-tls7mod.so-no-z-defs = yes
tst-tls77mod.so-no-z-defs = yes
ifeq ($(build-shared),yes)
# Build all the modules even when not actually running test programs.
@@ -391,8 +400,8 @@ $(inst_libdir)/libpthread.so: $(common-objpfx)format.lds \
echo ' Use the shared library, but some functions are only in';\
echo ' the static library, so try that secondarily. */';\
cat $<; \
echo 'GROUP ( $(slibdir)/libpthread.so$(libpthread.so-version)' \
'$(libdir)/$(patsubst %,$(libtype.oS),$(libprefix)pthread)'\
echo 'GROUP ( libpthread.so$(libpthread.so-version)' \
'$(patsubst %,$(libtype.oS),$(libprefix)pthread)'\
')' \
) > $@.new
mv -f $@.new $@
@@ -480,6 +489,12 @@ $(objpfx)tst-tls5: $(objpfx)tst-tls5mod.so $(shared-thread-library)
LDFLAGS-tst-tls5 = $(no-as-needed)
LDFLAGS-tst-tls5mod.so = -Wl,-soname,tst-tls5mod.so
# ensure free(malloc()) isn't optimized out
CFLAGS-tst-tls7.c = -fno-builtin-malloc -fno-builtin-free
$(objpfx)tst-tls7: $(libdl) $(shared-thread-library)
$(objpfx)tst-tls7.out: $(objpfx)tst-tls7mod.so
$(objpfx)tst-tls7mod.so: $(shared-thread-library)
ifeq ($(build-shared),yes)
ifeq ($(run-built-tests),yes)
tests: $(objpfx)tst-tls6.out
@@ -492,6 +507,11 @@ $(objpfx)tst-tls6.out: tst-tls6.sh $(objpfx)tst-tls5 \
'$(test-wrapper-env)'
endif
$(objpfx)tst-tls77: $(libdl) $(shared-thread-library)
LDFLAGS-tst-tls77 = -rdynamic
$(objpfx)tst-tls77.out: $(objpfx)tst-tls77mod.so
$(objpfx)tst-tls77mod.so: $(shared-thread-library)
$(objpfx)tst-dlsym1: $(libdl) $(shared-thread-library)
$(objpfx)tst-fini1: $(shared-thread-library) $(objpfx)tst-fini1mod.so
@@ -589,6 +609,8 @@ $(objpfx)tst-execstack: $(libdl)
$(objpfx)tst-execstack.out: $(objpfx)tst-execstack-mod.so
LDFLAGS-tst-execstack = -Wl,-z,noexecstack
$(objpfx)tst-key5: $(librt)
$(objpfx)tst-fini1mod.so: $(shared-thread-library)
tst-stackguard1-ARGS = --command "$(host-test-program-cmd) --child"
+1
View File
@@ -258,6 +258,7 @@ libpthread {
}
GLIBC_PRIVATE {
__google_pthread_signal_safe_key_create;
__pthread_initialize_minimal;
__pthread_clock_gettime; __pthread_clock_settime;
__pthread_unwind; __pthread_get_minstack;
+25 -9
View File
@@ -242,11 +242,7 @@ get_cached_stack (size_t *sizep, void **memp)
/* Clear the DTV. */
dtv_t *dtv = GET_DTV (TLS_TPADJ (result));
for (size_t cnt = 0; cnt < dtv[-1].counter; ++cnt)
if (! dtv[1 + cnt].pointer.is_static
&& dtv[1 + cnt].pointer.val != TLS_DTV_UNALLOCATED)
free (dtv[1 + cnt].pointer.val);
memset (dtv, '\0', (dtv[-1].counter + 1) * sizeof (dtv_t));
_dl_clear_dtv (dtv);
/* Re-initialize the TLS. */
_dl_allocate_tls_init (TLS_TPADJ (result));
@@ -660,6 +656,21 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
return errno;
}
/* The call to madvise(...MADV_DONTNEED) below will fail if pages
are locked. Unlock the guard memory to make sure the
madvise function succeeds (memory can be locked if
process called mlockall(MCL_FUTURE) at some point in the
past).*/
munlock (guard, guardsize);
/* We've marked this guard region unwritable, but it's
possible it already became resident, the most common case
being transparent hugepages; if stack + guard (+ adjacent
mmap regions) were more than 2MB, the kernel might have
filled in a full hugepage when we touched the thread
descriptor above. This can waste a lot of memory; mark
the guard unused. This shouldn't fail, but if it does,
we can't really do anything about it so ignore it. */
madvise (guard, guardsize, MADV_DONTNEED);
pd->guardsize = guardsize;
}
@@ -1177,13 +1188,18 @@ init_one_static_tls (struct pthread *curp, struct link_map *map)
# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
# endif
/* Fill in the DTV slot so that a later LD/GD access will find it. */
dtv[map->l_tls_modid].pointer.val = dest;
dtv[map->l_tls_modid].pointer.is_static = true;
/* Initialize the memory. */
memset (__mempcpy (dest, map->l_tls_initimage, map->l_tls_initimage_size),
'\0', map->l_tls_blocksize - map->l_tls_initimage_size);
/* Fill in the DTV slot so that a later LD/GD access will find it. */
dtv[map->l_tls_modid].pointer.is_static = true;
/* Pairs against the read barrier in tls_get_attr_tail, guaranteeing
any thread waiting for an update to pointer.val sees the
initimage write. */
atomic_write_barrier ();
dtv[map->l_tls_modid].pointer.val = dest;
}
void
+3 -9
View File
@@ -53,16 +53,10 @@ __pthread_getspecific (key)
data = &level2[idx2nd];
}
void *result = data->data;
if (result != NULL)
{
uintptr_t seq = data->seq;
if (__builtin_expect (data->seq != __pthread_keys[key].seq, 0))
return NULL;
if (__builtin_expect (seq != __pthread_keys[key].seq, 0))
result = data->data = NULL;
}
return result;
return data->data;
}
strong_alias (__pthread_getspecific, pthread_getspecific)
hidden_def (__pthread_getspecific)
+37 -16
View File
@@ -18,33 +18,54 @@
#include <errno.h>
#include "pthreadP.h"
#include <assert.h>
#include <atomic.h>
static int
claim_key (pthread_key_t *key, void (*destr) (void *), size_t cnt)
{
uintptr_t seq = __pthread_keys[cnt].seq;
if (KEY_UNUSED (seq) && KEY_USABLE (seq)
/* We found an unused slot. Try to allocate it. */
&& ! atomic_compare_and_exchange_bool_acq (&__pthread_keys[cnt].seq,
seq + 1, seq))
{
/* Remember the destructor. */
__pthread_keys[cnt].destr = destr;
/* Return the key to the caller. */
*key = cnt;
return 0;
}
return -1;
}
int
__pthread_key_create (key, destr)
pthread_key_t *key;
void (*destr) (void *);
{
/* Find a slot in __pthread_kyes which is unused. */
for (size_t cnt = 0; cnt < PTHREAD_KEYS_MAX; ++cnt)
/* Find a slot in __pthread_keys which is unused. */
for (size_t cnt = PTHREAD_SIGNAL_SAFE_KEYS_MAX; cnt < PTHREAD_KEYS_MAX; ++cnt)
{
uintptr_t seq = __pthread_keys[cnt].seq;
if (claim_key (key, destr, cnt) == 0)
return 0;
}
if (KEY_UNUSED (seq) && KEY_USABLE (seq)
/* We found an unused slot. Try to allocate it. */
&& ! atomic_compare_and_exchange_bool_acq (&__pthread_keys[cnt].seq,
seq + 1, seq))
{
/* Remember the destructor. */
__pthread_keys[cnt].destr = destr;
return EAGAIN;
}
/* Return the key to the caller. */
*key = cnt;
/* The call succeeded. */
return 0;
}
int __google_pthread_signal_safe_key_create (
pthread_key_t *key, void (*destr) (void *))
{
/* Our implementation makes signal safe keys easy: they just have to
reside in the first (inline) block. */
assert (PTHREAD_SIGNAL_SAFE_KEYS_MAX <= PTHREAD_KEY_1STLEVEL_SIZE);
/* Find a slot in __pthread_keys which is unused. */
for (size_t cnt = 0; cnt < PTHREAD_SIGNAL_SAFE_KEYS_MAX; ++cnt)
{
if (claim_key (key, destr, cnt) == 0)
return 0;
}
return EAGAIN;
+14
View File
@@ -1123,6 +1123,20 @@ extern int pthread_key_create (pthread_key_t *__key,
void (*__destr_function) (void *))
__THROW __nonnull ((1));
/* Exactly as pthread_key_create, but returns an async-signal-safe key:
getspecific, setspecific, and key_delete are async-signal-safe when
used with the returned key. The number of signal_safe keys is *extremely*
limited (PTHREAD_SIGNAL_SAFE_KEY_MAX); you are highly recommended to use
pthread_key_create unless it's absolutely necessary. This function
is async-signal-safe. */
#if !defined(IS_IN_libpthread)
__attribute__((weak))
#endif
extern int __google_pthread_signal_safe_key_create (pthread_key_t *__key,
void (*__destr_function) (void *))
__THROW __nonnull ((1));
/* Destroy KEY. */
extern int pthread_key_delete (pthread_key_t __key) __THROW;
@@ -22,6 +22,7 @@
#include <pthreadP.h>
#include <sysdep.h>
#include <gnu/lib-names.h>
#include <ldsodefs.h>
static void *libgcc_s_handle;
static void (*libgcc_s_resume) (struct _Unwind_Exception *exc);
@@ -51,6 +52,10 @@ pthread_cancel_init (void)
handle = __libc_dlopen (LIBGCC_S_SO);
/* Google-local: b/5836136 */
if (handle == NULL)
handle = GL(dl_ns)[LM_ID_BASE]._ns_loaded;
if (handle == NULL
|| (resume = __libc_dlsym (handle, "_Unwind_Resume")) == NULL
|| (personality = __libc_dlsym (handle, "__gcc_personality_v0")) == NULL
@@ -62,6 +62,7 @@
#define _POSIX_THREAD_KEYS_MAX 128
/* This is the value this implementation supports. */
#define PTHREAD_KEYS_MAX 1024
#define PTHREAD_SIGNAL_SAFE_KEYS_MAX 4
/* Controlling the iterations of destructors for thread-specific data. */
#define _POSIX_THREAD_DESTRUCTOR_ITERATIONS 4
@@ -62,6 +62,7 @@
#define _POSIX_THREAD_KEYS_MAX 128
/* This is the value this implementation supports. */
#define PTHREAD_KEYS_MAX 1024
#define PTHREAD_SIGNAL_SAFE_KEYS_MAX 4
/* Controlling the iterations of destructors for thread-specific data. */
#define _POSIX_THREAD_DESTRUCTOR_ITERATIONS 4
@@ -112,6 +112,36 @@ void
attribute_hidden
__linkin_atfork (struct fork_handler *newp)
{
/* GRTE's patches for async-signal-safe TLS can cause a race
condition in which ptmalloc_init is called from more than one
thread. (allocate_dtv normally calls calloc which invokes
ptmalloc_init via hook while creating the first thread, but our
code calls __signal_safe_calloc which does not run hooks.)
ptmalloc_init tries to be idempotent in case of multiple threads,
but in glibc-2.19, it fills in atfork hooks from an
un-lock-protected global static atfork_mem, which is a bad idea;
it can result in the same allocated object being passed to this
routine more than once. This function then sets the object's next
pointer to point to itself, resulting in a hang when the program
tries to exit.
This problem has been (indirectly) resolved in upstream glibc by
rewriting the whole thing so that thread setup is not done with
atforks or static variables, but the changes are extensive and
would not backport reliably. Our race is somewhat difficult to
trigger - it requires a program to start creating threads
*before* any kind of memory allocation whatsoever. So given all
this, the safest route is simply to detect when the fork handler
is already present, and skip adding it altogether.
Note that while it's conceivable that calls to pthread_atfork
would result in the atfork_mem object not being at the head of
the list, but testing seems unable to generate such a case. */
struct fork_handler *scanp;
for (scanp = __fork_handlers; scanp != NULL; scanp = scanp->next)
if (newp == scanp)
return;
do
newp->next = __fork_handlers;
while (catomic_compare_and_exchange_bool_acq (&__fork_handlers,
@@ -62,6 +62,7 @@
#define _POSIX_THREAD_KEYS_MAX 128
/* This is the value this implementation supports. */
#define PTHREAD_KEYS_MAX 1024
#define PTHREAD_SIGNAL_SAFE_KEYS_MAX 4
/* Controlling the iterations of destructors for thread-specific data. */
#define _POSIX_THREAD_DESTRUCTOR_ITERATIONS 4
+91
View File
@@ -0,0 +1,91 @@
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <pthread.h>
/* Test that stack guards do not become resident, even with
mlockall(MCL_FUTURE) by verifying that spawning NTHREADS with these
stack/guard sizes use a reasonable (<100kb/thread) amount of RSS. */
#define NTHREADS 100
#define STACKSIZE (64 * 1024)
#define GUARDSIZE (1024 * 1024)
pthread_barrier_t barrier;
static void fail (const char *msg)
{
puts (msg);
exit (1);
}
static size_t get_rss_bytes (void)
{
struct rusage usage;
if (getrusage(RUSAGE_SELF, &usage) != 0)
fail ("getrusage failed");
return usage.ru_maxrss * 1024;
}
static void *
child (void *arg)
{
int ret = pthread_barrier_wait(&barrier);
if (ret != 0 && ret != PTHREAD_BARRIER_SERIAL_THREAD)
fail("pthread_barrier_wait failed");
while (1)
{
sleep (10);
}
return NULL;
}
static int
do_test (void)
{
int err;
int i;
size_t bytes;
char buffer[2048];
size_t overhead, count;
int fd;
mlockall(MCL_CURRENT);
overhead = get_rss_bytes();
mlockall(MCL_CURRENT|MCL_FUTURE);
if (pthread_barrier_init(&barrier, NULL, NTHREADS + 1) != 0)
fail("pthread_barrier_init failed");
for (i = 0; i < NTHREADS; ++i)
{
pthread_attr_t attr;
pthread_t tid;
pthread_attr_init (&attr);
pthread_attr_setstacksize (&attr, STACKSIZE + GUARDSIZE);
pthread_attr_setguardsize (&attr, GUARDSIZE);
err = pthread_create (&tid, &attr, child, NULL);
if (err != 0)
fail("pthread_create failed");
}
err = pthread_barrier_wait(&barrier);
if (err != 0 && err != PTHREAD_BARRIER_SERIAL_THREAD)
fail("pthread_barrier_wait failed");
bytes = get_rss_bytes ();
fd = open("/proc/self/smaps", O_RDONLY);
while(0 < (count = read(fd, buffer, 2048)))
write(1, buffer, count);
close(fd);
printf ("%d threads with %d stacks and %d guards using %zu per thread\n",
NTHREADS, STACKSIZE, GUARDSIZE, (bytes-overhead)/NTHREADS);
if ((bytes-overhead) > (NTHREADS * GUARDSIZE))
fail ("memory usage too high");
return 0;
}
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"
+4
View File
@@ -28,7 +28,11 @@ do_test (void)
{
int max;
#ifdef PTHREAD_KEYS_MAX
#ifdef PTHREAD_SIGNAL_SAFE_KEYS_MAX
max = PTHREAD_KEYS_MAX - PTHREAD_SIGNAL_SAFE_KEYS_MAX;
#else
max = PTHREAD_KEYS_MAX;
#endif
#else
max = _POSIX_THREAD_KEYS_MAX;
#endif
+4
View File
@@ -24,7 +24,11 @@
#ifdef PTHREAD_KEYS_MAX
#ifdef PTHREAD_SIGNAL_SAFE_KEYS_MAX
const int max = PTHREAD_KEYS_MAX - PTHREAD_SIGNAL_SAFE_KEYS_MAX;
#else
const int max = PTHREAD_KEYS_MAX;
#endif
#else
const int max = _POSIX_THREAD_KEYS_MAX;
#endif
+77
View File
@@ -0,0 +1,77 @@
/* Copyright (C) 2014 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <pthread.h>
#include <unistd.h>
#include <signal.h>
#include <time.h>
#include <assert.h>
#include <string.h>
#include <stdio.h>
pthread_key_t key;
void *value;
size_t r;
static void
handler (int signo)
{
void *ret = pthread_getspecific (key);
/* We race with the setspecific--either result is fine, just not junk. */
assert (ret == value || ret == NULL);
r++;
}
int
do_test (void)
{
struct sigaction sa;
memset (&sa, 0, sizeof (sa));
sa.sa_handler = handler;
assert (0 == sigaction (SIGUSR1, &sa, NULL));
timer_t timer;
struct sigevent sevp;
sevp.sigev_notify = SIGEV_SIGNAL;
sevp.sigev_signo = SIGUSR1;
assert (0 == timer_create(CLOCK_MONOTONIC, &sevp, &timer));
struct itimerspec spec;
spec.it_value.tv_sec = 0;
spec.it_value.tv_nsec = 500;
spec.it_interval = spec.it_value;
timer_settime(timer, 0, &spec, NULL);
#define NITERS (1000 * 1000)
for (int i = 0; i < NITERS; ++i)
{
value = (void *)((intptr_t)i + 1);
assert (0 == pthread_key_create(&key, NULL));
assert (0 == pthread_setspecific(key, value));
if (value != pthread_getspecific(key))
{
printf ("Lost a value\n");
return 1;
}
assert (0 == pthread_key_delete(key));
}
timer_delete(timer);
return 0;
}
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"
+143
View File
@@ -0,0 +1,143 @@
/* Copyright (C) 2013 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
/* This test checks that TLS in a dlopened object works when first accessed
from a signal handler. */
#include <assert.h>
#include <atomic.h>
#include <dlfcn.h>
#include <pthread.h>
#include <semaphore.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
void *
spin (void *ignored)
{
while (1)
{
/* busywork */
free (malloc (128));
}
/* never reached */
return NULL;
}
static void (*tls7mod_action) (int, siginfo_t *, void *);
static void
action (int signo, siginfo_t *info, void *ignored)
{
sem_t *sem = info->si_value.sival_ptr;
atomic_read_barrier ();
assert (tls7mod_action != NULL);
(*tls7mod_action) (signo, info, ignored);
/* This sem_post may trigger dlclose, which will invalidate tls7mod_action.
It is important to do that only after tls7mod_action is no longer
active. */
sem_post (sem);
}
int
do_test (void)
{
pthread_t th[10];
for (int i = 0; i < 10; ++i)
{
if (pthread_create (&th[i], NULL, spin, NULL))
{
puts ("pthread_create failed");
exit (1);
}
}
#define NITERS 75
for (int i = 0; i < NITERS; ++i)
{
void *h = dlopen ("tst-tls7mod.so", RTLD_LAZY);
if (h == NULL)
{
puts ("dlopen failed");
exit (1);
}
tls7mod_action = dlsym (h, "action");
if (tls7mod_action == NULL)
{
puts ("dlsym for action failed");
exit (1);
}
atomic_write_barrier ();
struct sigaction sa;
sa.sa_sigaction = action;
sigemptyset (&sa.sa_mask);
sa.sa_flags = SA_SIGINFO;
if (sigaction (SIGUSR1, &sa, NULL))
{
puts ("sigaction failed");
exit (1);
}
sem_t sem;
if (sem_init (&sem, 0, 0))
{
puts ("sem_init failed");
}
sigval_t val;
val.sival_ptr = &sem;
for (int i = 0; i < 10; ++i)
{
if (pthread_sigqueue (th[i], SIGUSR1, val))
{
puts ("pthread_sigqueue failed");
}
}
for (int i = 0; i < 10; ++i)
{
if (sem_wait (&sem))
{
puts ("sem_wait failed");
}
}
/* Paranoia. */
tls7mod_action = NULL;
if (dlclose (h))
{
puts ("dlclose failed");
exit (1);
}
}
return 0;
}
#define TIMEOUT 8
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"
+107
View File
@@ -0,0 +1,107 @@
/* Copyright (C) 2015 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <dlfcn.h>
#include <errno.h>
#include <pthread.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthreaddef.h>
static pthread_t th;
pthread_barrier_t b;
void *(*dfp)(void*) = NULL;
void *
caller(void *x)
{
pthread_barrier_wait (&b);
if (dfp)
dfp(NULL);
return NULL;
}
int
do_test (void)
{
if (pthread_barrier_init (&b, NULL, 2) != 0)
{
puts ("barrier_init failed");
exit (1);
}
pthread_attr_t a;
if (pthread_attr_init (&a) != 0)
{
puts ("attr_init failed");
exit (1);
}
if (pthread_attr_setstacksize (&a, 1 * 1024 * 1024) != 0)
{
puts ("attr_setstacksize failed");
return 1;
}
if (pthread_create (&th, &a, caller, 0) != 0)
{
puts ("pthread_create failed");
exit (1);
}
void *h = dlopen ("tst-tls77mod.so", RTLD_LAZY);
if (h == NULL)
{
puts ("dlopen failed");
exit (1);
}
dfp = dlsym (h, "toucher");
if (dfp == NULL)
{
printf ("dlsym for toucher failed %s\n", dlerror ());
return 1;
}
pthread_barrier_wait (&b);
if (pthread_join (th, NULL) != 0)
{
puts ("join failed");
exit (1);
}
if (pthread_attr_destroy (&a) != 0)
{
puts ("attr_destroy failed");
exit (1);
}
return 0;
}
#define TIMEOUT 5
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"
+41
View File
@@ -0,0 +1,41 @@
/* Copyright (C) 2015 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <pthread.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthreaddef.h>
__thread int tlsvar;
__thread int iexecvar __attribute__ ((tls_model ("initial-exec")));
void *
toucher (void *arg)
{
tlsvar++;
printf ("tlsvar=%d iexecvar=%d\n", tlsvar, iexecvar);
iexecvar++;
printf ("tlsvar=%d iexecvar=%d\n", tlsvar, iexecvar);
return NULL;
}
+40
View File
@@ -0,0 +1,40 @@
/* Copyright (C) 2013 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
/* Dynamic module with TLS to be accessed by a signal handler to check safety
of that mode. */
#include <semaphore.h>
#include <signal.h>
#include <unistd.h>
/* This is an unlikely value to see in incorrectly initialized TLS
block -- make sure we're initialized properly. */
static __thread intptr_t tls_data = 0xdeadbeef;
void
action (int signo, siginfo_t *info, void *ignored)
{
if (tls_data != 0xdeadbeef)
{
write (STDOUT_FILENO, "wrong TLS value\n", 17);
_exit (1);
}
/* arbitrary choice, just write something unique-ish. */
tls_data = (intptr_t) info;
}

Some files were not shown because too many files have changed in this diff Show More