summaryrefslogtreecommitdiff
path: root/elf
diff options
context:
space:
mode:
authorSamuel Thibault <samuel.thibault@ens-lyon.org>2016-08-20 20:54:39 +0200
committerSamuel Thibault <samuel.thibault@ens-lyon.org>2016-08-20 20:54:39 +0200
commit29af7775cfef6ed3b466b92e44387574122ed61b (patch)
treec968738daba6d87d69dc4e8b4cb1445a7b6420cb /elf
parent4893e0ed57daaff901442bacc10ae09cd3e1850f (diff)
parentf76453c31593957fec1a99b986bfa5506618b79c (diff)
Merge branch 'baseline' into refs/top-bases/tschwinge/Roger_Whittaker
Diffstat (limited to 'elf')
-rw-r--r--elf/Makefile317
-rw-r--r--elf/Versions3
-rw-r--r--elf/cache.c6
-rw-r--r--elf/chroot_canon.c2
-rw-r--r--elf/dl-addr.c2
-rw-r--r--elf/dl-cache.c27
-rw-r--r--elf/dl-caller.c2
-rw-r--r--elf/dl-close.c78
-rw-r--r--elf/dl-conflict.c4
-rw-r--r--elf/dl-debug.c2
-rw-r--r--elf/dl-deps.c92
-rw-r--r--elf/dl-dst.h4
-rw-r--r--elf/dl-environ.c2
-rw-r--r--elf/dl-error.c2
-rw-r--r--elf/dl-execstack.c2
-rw-r--r--elf/dl-fini.c12
-rw-r--r--elf/dl-fptr.c8
-rw-r--r--elf/dl-hwcaps.c4
-rw-r--r--elf/dl-init.c17
-rw-r--r--elf/dl-iteratephdr.c2
-rw-r--r--elf/dl-libc.c8
-rw-r--r--elf/dl-load.c555
-rw-r--r--elf/dl-load.h135
-rw-r--r--elf/dl-lookup.c665
-rw-r--r--elf/dl-machine-reject-phdr.h34
-rw-r--r--elf/dl-map-segments.h153
-rw-r--r--elf/dl-minimal.c44
-rw-r--r--elf/dl-misc.c2
-rw-r--r--elf/dl-object.c2
-rw-r--r--elf/dl-open.c73
-rw-r--r--elf/dl-origin.c2
-rw-r--r--elf/dl-profile.c4
-rw-r--r--elf/dl-profstub.c2
-rw-r--r--elf/dl-reloc.c60
-rw-r--r--elf/dl-runtime.c10
-rw-r--r--elf/dl-scope.c2
-rw-r--r--elf/dl-support.c10
-rw-r--r--elf/dl-sym.c10
-rw-r--r--elf/dl-symaddr.c3
-rw-r--r--elf/dl-sysdep.c12
-rw-r--r--elf/dl-tls.c219
-rw-r--r--elf/dl-tsd.c2
-rw-r--r--elf/dl-unmap-segments.h35
-rw-r--r--elf/dl-version.c12
-rw-r--r--elf/dl-writev.h4
-rw-r--r--elf/do-rel.h2
-rw-r--r--elf/dynamic-link.h14
-rw-r--r--elf/elf.h221
-rw-r--r--elf/enbl-secure.c2
-rw-r--r--elf/get-dynamic-info.h13
-rw-r--r--elf/ifuncdep2.c8
-rw-r--r--elf/ifuncmod1.c8
-rw-r--r--elf/ifuncmod5.c8
-rw-r--r--elf/interp.c4
-rw-r--r--elf/ldconfig.c34
-rw-r--r--elf/ldd.bash.in4
-rw-r--r--elf/link.h2
-rw-r--r--elf/pldd-xx.c34
-rw-r--r--elf/pldd.c53
-rw-r--r--elf/readelflib.c2
-rw-r--r--elf/readlib.c12
-rw-r--r--elf/rtld-Rules7
-rw-r--r--elf/rtld.c318
-rw-r--r--elf/setup-vdso.h6
-rw-r--r--elf/sln.c2
-rw-r--r--elf/sotruss-lib.c2
-rwxr-xr-xelf/sotruss.sh (renamed from elf/sotruss.ksh)15
-rw-r--r--elf/sprof.c6
-rw-r--r--elf/static-stubs.c2
-rw-r--r--elf/tlsdeschtab.h14
-rw-r--r--elf/tst-align.c2
-rw-r--r--elf/tst-align2.c2
-rw-r--r--elf/tst-alignmod.c2
-rw-r--r--elf/tst-alignmod2.c2
-rw-r--r--elf/tst-audit2.c33
-rw-r--r--elf/tst-audit9.c12
-rw-r--r--elf/tst-auditmod9a.c15
-rw-r--r--elf/tst-auditmod9b.c6
-rw-r--r--elf/tst-auxv.c2
-rw-r--r--elf/tst-dl-iter-static.c47
-rw-r--r--elf/tst-dlmodcount.c2
-rw-r--r--elf/tst-dlopen-aout.c67
-rw-r--r--elf/tst-dlopenrpath.c2
-rw-r--r--elf/tst-dlopenrpathmod.c2
-rw-r--r--elf/tst-global1.c7
-rw-r--r--elf/tst-leaks1.c7
-rw-r--r--elf/tst-nodelete-opened-lib.c19
-rw-r--r--elf/tst-nodelete-opened.c69
-rw-r--r--elf/tst-nodelete-rtldmod.cc6
-rw-r--r--elf/tst-nodelete-uniquemod.cc14
-rw-r--r--elf/tst-nodelete-zmod.cc6
-rw-r--r--elf/tst-nodelete.cc51
-rw-r--r--elf/tst-null-argv-lib.c2
-rw-r--r--elf/tst-null-argv.c2
-rw-r--r--elf/tst-pathopt.c7
-rwxr-xr-xelf/tst-pathopt.sh7
-rw-r--r--elf/tst-pie2.c38
-rw-r--r--elf/tst-piemod1.c7
-rw-r--r--elf/tst-protected1a.c236
-rw-r--r--elf/tst-protected1b.c242
-rw-r--r--elf/tst-protected1mod.h41
-rw-r--r--elf/tst-protected1moda.c92
-rw-r--r--elf/tst-protected1modb.c62
-rw-r--r--elf/tst-ptrguard1.c2
-rwxr-xr-xelf/tst-rtld-load-self.sh2
-rw-r--r--elf/tst-stackguard1.c2
-rw-r--r--elf/tst-tls10.c7
-rw-r--r--elf/tst-tls11.c7
-rw-r--r--elf/tst-tls12.c7
-rw-r--r--elf/tst-tlsalign-extern-static.c1
-rw-r--r--elf/tst-tlsalign-extern.c74
-rw-r--r--elf/tst-tlsalign-lib.c6
-rw-r--r--elf/tst-tlsalign-static.c2
-rw-r--r--elf/tst-tlsalign-vars.c28
-rw-r--r--elf/tst-tlsalign.c85
-rw-r--r--elf/tst-unique4lib.cc4
-rw-r--r--elf/tst-znodelete-zlib.cc6
-rw-r--r--elf/vismain.c7
-rw-r--r--elf/vismod1.c2
-rw-r--r--elf/vismod2.c2
-rw-r--r--elf/vismod3.c2
121 files changed, 3339 insertions, 1457 deletions
diff --git a/elf/Makefile b/elf/Makefile
index 4c58fc9c24..4ceeaf89be 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -1,4 +1,4 @@
-# Copyright (C) 1995-2014 Free Software Foundation, Inc.
+# Copyright (C) 1995-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
@@ -22,7 +22,7 @@ subdir := elf
include ../Makeconfig
headers = elf.h bits/elfclass.h link.h bits/link.h
-routines = $(dl-routines) dl-support dl-iteratephdr \
+routines = $(all-dl-routines) dl-support dl-iteratephdr \
dl-addr enbl-secure dl-profstub \
dl-origin dl-libc dl-sym dl-tsd dl-sysdep
@@ -43,7 +43,7 @@ shared-only-routines += dl-caller
# ld.so uses those routines, plus some special stuff for being the program
# interpreter and operating independent of libc.
-rtld-routines := rtld $(dl-routines) dl-sysdep dl-environ dl-minimal
+rtld-routines = rtld $(all-dl-routines) dl-sysdep dl-environ dl-minimal
all-rtld-routines = $(rtld-routines) $(sysdep-rtld-routines)
CFLAGS-dl-runtime.c = -fexceptions -fasynchronous-unwind-tables
@@ -55,9 +55,9 @@ routines += unwind-dw2-fde-glibc
shared-only-routines += unwind-dw2-fde-glibc
endif
-before-compile = $(objpfx)trusted-dirs.h
-generated := trusted-dirs.h trusted-dirs.st for-renamed/renamed.so
-generated-dirs := for-renamed
+before-compile += $(objpfx)trusted-dirs.h
+generated += trusted-dirs.h trusted-dirs.st for-renamed/renamed.so
+generated-dirs += for-renamed
ifeq ($(build-shared),yes)
ld-map = $(common-objpfx)ld.map
@@ -70,8 +70,8 @@ install-others = $(inst_rtlddir)/$(rtld-installed-name)
install-bin-script = ldd
endif
-others = sprof sln pldd
-install-bin = sprof pldd
+others = sprof sln
+install-bin = sprof
others-static = sln
install-rootsbin = sln
sln-modules := static-stubs
@@ -88,24 +88,22 @@ extra-objs += $(ldconfig-modules:=.o)
endif
endif
-pldd-modules := xmalloc
-
# To find xmalloc.c and xstrdup.c
vpath %.c ../locale/programs
-ifeq ($(have-ksh)$(build-shared),yesyes)
+ifeq ($(build-shared),yes)
extra-objs += sotruss-lib.os sotruss-lib.so
install-others += $(inst_auditdir)/sotruss-lib.so
install-bin-script += sotruss
generated += sotruss
-CPPFLAGS-sotruss-lib = -DNOT_IN_libc
+libof-sotruss-lib = extramodules
$(objpfx)sotruss-lib.so: $(objpfx)sotruss-lib.os
$(build-module-asneeded)
$(objpfx)sotruss-lib.so: $(common-objpfx)libc.so $(objpfx)ld.so \
$(common-objpfx)libc_nonshared.a
-$(objpfx)sotruss: sotruss.ksh $(common-objpfx)config.make
- sed -e 's%@KSH@%$(KSH)%g' \
+$(objpfx)sotruss: sotruss.sh $(common-objpfx)config.make
+ sed -e 's%@BASH@%$(BASH)%g' \
-e 's%@VERSION@%$(version)%g' \
-e 's%@TEXTDOMAINDIR@%$(msgcatdir)%g' \
-e 's%@PREFIX@%$(prefix)%g' \
@@ -123,7 +121,8 @@ tests = tst-tls1 tst-tls2 tst-tls9 tst-leaks1 \
tst-auxv
tests-static = tst-tls1-static tst-tls2-static tst-stackguard1-static \
tst-leaks1-static tst-array1-static tst-array5-static \
- tst-ptrguard1-static
+ tst-ptrguard1-static tst-dl-iter-static \
+ tst-tlsalign-static tst-tlsalign-extern-static
ifeq (yes,$(build-shared))
tests-static += tst-tls9-static
tst-tls9-static-ENV = \
@@ -132,7 +131,7 @@ endif
tests += $(tests-static)
ifeq (yes,$(build-shared))
tests += loadtest restest1 preloadtest loadfail multiload origtest resolvfail \
- constload1 order vismain noload filter unload \
+ constload1 order noload filter unload \
reldep reldep2 reldep3 reldep4 nodelete nodelete2 \
nodlopen nodlopen2 neededtest neededtest2 \
neededtest3 neededtest4 unload2 lateglobal initfirst global \
@@ -144,12 +143,17 @@ tests += loadtest restest1 preloadtest loadfail multiload origtest resolvfail \
tst-dlmodcount tst-dlopenrpath tst-deep1 \
tst-dlmopen1 tst-dlmopen2 tst-dlmopen3 \
unload3 unload4 unload5 unload6 unload7 unload8 tst-global1 order2 \
- tst-audit1 tst-audit2 tst-audit8 \
+ tst-audit1 tst-audit2 tst-audit8 tst-audit9 \
tst-stackguard1 tst-addr1 tst-thrlock \
- tst-unique1 tst-unique2 tst-unique3 tst-unique4 \
+ tst-unique1 tst-unique2 $(if $(CXX),tst-unique3 tst-unique4 \
+ tst-nodelete) \
tst-initorder tst-initorder2 tst-relsort1 tst-null-argv \
- tst-ptrguard1
+ tst-ptrguard1 tst-tlsalign tst-tlsalign-extern tst-nodelete-opened
# reldep9
+ifeq ($(build-hardcoded-path-in-tests),yes)
+tests += tst-dlopen-aout
+LDFLAGS-tst-dlopen-aout = $(no-pie-ldflag)
+endif
test-srcs = tst-pathopt
selinux-enabled := $(shell cat /selinux/enforce 2> /dev/null)
ifneq ($(selinux-enabled),1)
@@ -157,8 +161,8 @@ tests-execstack-yes = tst-execstack tst-execstack-needed tst-execstack-prog
endif
endif
ifeq ($(run-built-tests),yes)
-tests: $(objpfx)tst-leaks1-mem $(objpfx)tst-leaks1-static-mem \
- $(objpfx)noload-mem
+tests-special += $(objpfx)tst-leaks1-mem.out \
+ $(objpfx)tst-leaks1-static-mem.out $(objpfx)noload-mem.out
endif
tlsmod17a-suffixes = 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
tlsmod18a-suffixes = 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
@@ -203,19 +207,32 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
order2mod1 order2mod2 order2mod3 order2mod4 \
tst-unique1mod1 tst-unique1mod2 \
tst-unique2mod1 tst-unique2mod2 \
- tst-unique3lib tst-unique3lib2 \
- tst-unique4lib \
+ tst-auditmod9a tst-auditmod9b \
+ $(if $(CXX),tst-unique3lib tst-unique3lib2 tst-unique4lib \
+ tst-nodelete-uniquemod tst-nodelete-rtldmod \
+ tst-nodelete-zmod) \
tst-initordera1 tst-initorderb1 \
tst-initordera2 tst-initorderb2 \
tst-initordera3 tst-initordera4 \
tst-initorder2a tst-initorder2b tst-initorder2c \
tst-initorder2d \
tst-relsort1mod1 tst-relsort1mod2 tst-array2dep \
- tst-array5dep tst-null-argv-lib
+ tst-array5dep tst-null-argv-lib \
+ tst-tlsalign-lib tst-nodelete-opened-lib
+ifeq (yes,$(have-protected-data))
+modules-names += tst-protected1moda tst-protected1modb
+tests += tst-protected1a tst-protected1b
+$(objpfx)tst-protected1a: $(addprefix $(objpfx),tst-protected1moda.so tst-protected1modb.so)
+$(objpfx)tst-protected1b: $(addprefix $(objpfx),tst-protected1modb.so tst-protected1moda.so)
+tst-protected1modb.so-no-z-defs = yes
+endif
ifeq (yesyes,$(have-fpie)$(build-shared))
modules-names += tst-piemod1
-tests += tst-pie1
-tests-pie += tst-pie1
+tests += tst-pie1 tst-pie2
+tests-pie += tst-pie1 tst-pie2
+tests += vismain
+tests-pie += vismain
+CFLAGS-vismain.c = $(PIE-ccflag)
endif
modules-execstack-yes = tst-execstack-mod
extra-test-objs += $(addsuffix .os,$(strip $(modules-names)))
@@ -252,12 +269,31 @@ modules-names += ifuncmod1 ifuncmod3 ifuncmod5 ifuncmod6
endif
endif
+ifeq (yes,$(build-shared))
+ifeq ($(run-built-tests),yes)
+tests-special += $(objpfx)tst-pathopt.out $(objpfx)tst-rtld-load-self.out
+endif
+tests-special += $(objpfx)check-textrel.out $(objpfx)check-execstack.out \
+ $(objpfx)check-localplt.out
+endif
-include ../Rules
+ifeq ($(run-built-tests),yes)
+tests-special += $(objpfx)order-cmp.out $(objpfx)tst-array1-cmp.out \
+ $(objpfx)tst-array1-static-cmp.out \
+ $(objpfx)tst-array2-cmp.out $(objpfx)tst-array3-cmp.out \
+ $(objpfx)tst-array4-cmp.out $(objpfx)tst-array5-cmp.out \
+ $(objpfx)tst-array5-static-cmp.out $(objpfx)order2-cmp.out \
+ $(objpfx)tst-initorder-cmp.out \
+ $(objpfx)tst-initorder2-cmp.out $(objpfx)tst-unused-dep.out \
+ $(objpfx)tst-unused-dep-cmp.out
+endif
-check-abi: check-abi-ld
+check-abi: $(objpfx)check-abi-ld.out
+tests-special += $(objpfx)check-abi-ld.out
update-abi: update-abi-ld
+include ../Rules
+
ifeq (yes,$(build-shared))
# Make sure these things are built in the `make lib' pass so they can be used
# to run programs during the `make others' pass.
@@ -328,21 +364,21 @@ $(objpfx)ld.so: $(objpfx)librtld.os $(ld-map)
$(filter-out $(map-file),$^) $(load-map-file) \
-Wl,-soname=$(rtld-installed-name) \
-Wl,-defsym=_begin=0
+ $(call after-link,$@.new)
$(READELF) -s $@.new \
| $(AWK) '($$7 ~ /^UND(|EF)$$/ && $$1 != "0:" && $$4 != "REGISTER") { print; p=1 } END { exit p != 0 }'
mv -f $@.new $@
-# interp.c exists just to get this string into the libraries.
-CFLAGS-interp.c = -D'RUNTIME_LINKER="$(rtlddir)/$(rtld-installed-name)"' \
- -DNOT_IN_libc=1
-$(objpfx)interp.os: $(common-objpfx)config.make
+ifeq (yes,$(build-shared))
+# interp.c exists just to get the runtime linker path into libc.so.
+$(objpfx)interp.os: $(common-objpfx)runtime-linker.h
+endif
ifneq (ld.so,$(rtld-installed-name))
# Make sure ld.so.1 exists in the build directory so we can link
# against it.
$(objpfx)$(rtld-installed-name): $(objpfx)ld.so
- rm -f $@
- ln -s $(<F) $@
+ $(make-link)
generated += $(rtld-installed-name)
endif
@@ -377,27 +413,20 @@ ldso_install: $(inst_rtlddir)/$(rtld-installed-name)
endif
-common-ldd-rewrite = -e 's%@RTLD@%$(rtlddir)/$(rtld-installed-name)%g' \
- -e 's%@VERSION@%$(version)%g' \
- -e 's|@PKGVERSION@|$(PKGVERSION)|g' \
- -e 's|@REPORT_BUGS_TO@|$(REPORT_BUGS_TO)|g'
-sh-ldd-rewrite = $(common-ldd-rewrite) -e 's%@BASH@%/bin/sh%g;s/\$$"/"/g'
-bash-ldd-rewrite = $(common-ldd-rewrite) -e 's%@BASH@%$(BASH)%g' \
- -e 's%@TEXTDOMAINDIR@%$(msgcatdir)%g'
-
-ifneq ($(have-bash2),yes)
-ldd-shell = sh
-else
-ldd-shell = bash
-endif
+ldd-rewrite = -e 's%@RTLD@%$(rtlddir)/$(rtld-installed-name)%g' \
+ -e 's%@VERSION@%$(version)%g' \
+ -e 's|@PKGVERSION@|$(PKGVERSION)|g' \
+ -e 's|@REPORT_BUGS_TO@|$(REPORT_BUGS_TO)|g' \
+ -e 's%@BASH@%$(BASH)%g' \
+ -e 's%@TEXTDOMAINDIR@%$(msgcatdir)%g'
ifeq ($(ldd-rewrite-script),no)
define gen-ldd
-LC_ALL=C sed $($(ldd-shell)-ldd-rewrite) < $< > $@.new
+LC_ALL=C sed $(ldd-rewrite) < $< > $@.new
endef
else
define gen-ldd
-LC_ALL=C sed $($(ldd-shell)-ldd-rewrite) < $< \
+LC_ALL=C sed $(ldd-rewrite) < $< \
| LC_ALL=C sed -f $(patsubst $(..)/%,/%,$(..)$(ldd-rewrite-script)) > $@.new
endef
endif
@@ -414,27 +443,21 @@ $(objpfx)sln: $(sln-modules:%=$(objpfx)%.o)
$(objpfx)ldconfig: $(ldconfig-modules:%=$(objpfx)%.o)
-$(objpfx)pldd: $(pldd-modules:%=$(objpfx)%.o)
-
SYSCONF-FLAGS := -D'SYSCONFDIR="$(sysconfdir)"'
CFLAGS-ldconfig.c = $(SYSCONF-FLAGS) -D'LIBDIR="$(libdir)"' \
- -D'SLIBDIR="$(slibdir)"' -DIS_IN_ldconfig=1
+ -D'SLIBDIR="$(slibdir)"'
+libof-ldconfig = ldconfig
CFLAGS-dl-cache.c = $(SYSCONF-FLAGS)
CFLAGS-cache.c = $(SYSCONF-FLAGS)
CFLAGS-rtld.c = $(SYSCONF-FLAGS)
-CPPFLAGS-.os += $(if $(filter $(@F),$(patsubst %,%.os,$(all-rtld-routines))),\
- -DNOT_IN_libc=1 -DIS_IN_rtld=1 -DIN_LIB=rtld)
+cpp-srcs-left := $(all-rtld-routines:=.os)
+lib := rtld
+include $(patsubst %,$(..)cppflags-iterator.mk,$(cpp-srcs-left))
test-modules = $(addprefix $(objpfx),$(addsuffix .so,$(strip $(modules-names))))
generated += $(addsuffix .so,$(strip $(modules-names)))
-ifeq (yes,$(build-shared))
-ifeq ($(run-built-tests),yes)
-tests: $(objpfx)tst-pathopt.out $(objpfx)tst-rtld-load-self.out
-endif
-endif
-
$(objpfx)testobj1.so: $(libdl)
$(objpfx)testobj1_1.so: $(objpfx)testobj1.so $(libdl)
$(objpfx)testobj2.so: $(objpfx)testobj1.so $(libdl)
@@ -501,6 +524,12 @@ $(objpfx)tst-initordera3.so: $(objpfx)tst-initorderb2.so $(objpfx)tst-initorderb
$(objpfx)tst-initordera4.so: $(objpfx)tst-initordera3.so
$(objpfx)tst-initorder: $(objpfx)tst-initordera4.so $(objpfx)tst-initordera1.so $(objpfx)tst-initorderb2.so
$(objpfx)tst-null-argv: $(objpfx)tst-null-argv-lib.so
+$(objpfx)tst-tlsalign: $(objpfx)tst-tlsalign-lib.so
+$(objpfx)tst-nodelete-opened.out: $(objpfx)tst-nodelete-opened-lib.so
+$(objpfx)tst-nodelete-opened: $(libdl)
+
+$(objpfx)tst-tlsalign-extern: $(objpfx)tst-tlsalign-vars.o
+$(objpfx)tst-tlsalign-extern-static: $(objpfx)tst-tlsalign-vars.o
tst-null-argv-ENV = LD_DEBUG=all LD_DEBUG_OUTPUT=$(objpfx)tst-null-argv.debug.out
LDFLAGS-nodel2mod3.so = $(no-as-needed)
@@ -515,8 +544,8 @@ LDFLAGS-tst-initordera2.so = $(no-as-needed)
LDFLAGS-tst-initordera3.so = $(no-as-needed)
LDFLAGS-tst-initordera4.so = $(no-as-needed)
LDFLAGS-tst-initorderb2.so = $(no-as-needed)
-LDFLAGS-tst-tlsmod5.so = -nostdlib
-LDFLAGS-tst-tlsmod6.so = -nostdlib
+LDFLAGS-tst-tlsmod5.so = -nostdlib $(no-as-needed)
+LDFLAGS-tst-tlsmod6.so = -nostdlib $(no-as-needed)
testobj1.so-no-z-defs = yes
testobj3.so-no-z-defs = yes
@@ -560,6 +589,11 @@ unload4mod1.so-no-z-defs = yes
ifuncmod1.so-no-z-defs = yes
ifuncmod5.so-no-z-defs = yes
ifuncmod6.so-no-z-defs = yes
+tst-auditmod9a.so-no-z-defs = yes
+tst-auditmod9b.so-no-z-defs = yes
+tst-nodelete-uniquemod.so-no-z-defs = yes
+tst-nodelete-rtldmod.so-no-z-defs = yes
+tst-nodelete-zmod.so-no-z-defs = yes
ifeq ($(build-shared),yes)
# Build all the modules even when not actually running test programs.
@@ -583,7 +617,6 @@ $(objpfx)neededtest3: $(libdl)
$(objpfx)neededtest3.out: $(objpfx)neededobj1.so $(objpfx)neededobj2.so \
$(objpfx)neededobj3.so $(objpfx)neededobj4.so
-neededtest4-ENV = LC_ALL=C LANGUAGE=C
$(objpfx)neededtest4: $(libdl) $(objpfx)neededobj1.so
$(objpfx)neededtest4.out: $(objpfx)neededobj5.so $(objpfx)neededobj6.so
@@ -637,21 +670,21 @@ $(objpfx)circlemod2a.so: $(objpfx)circlemod3a.so
$(objpfx)order: $(addprefix $(objpfx),dep4.so dep3.so dep2.so dep1.so)
-$(objpfx)order.out: $(objpfx)order
- $(test-program-prefix) \
- $(objpfx)order > $@
- (echo "0123456789" | cmp $@ -) > /dev/null
+$(objpfx)order-cmp.out: $(objpfx)order.out
+ (echo "0123456789" | cmp $< -) > $@; \
+ $(evaluate-test)
$(objpfx)vismain: $(addprefix $(objpfx),vismod1.so vismod2.so)
$(objpfx)vismain.out: $(addprefix $(objpfx),vismod3.so)
vismain-ENV = LD_PRELOAD=$(addprefix $(objpfx),vismod3.so)
-$(objpfx)noload: $(objpfx)testobj1.so $(common-objpfx)dlfcn/libdl.so
+$(objpfx)noload: $(objpfx)testobj1.so $(libdl)
LDFLAGS-noload = -rdynamic $(no-as-needed)
$(objpfx)noload.out: $(objpfx)testobj5.so
-$(objpfx)noload-mem: $(objpfx)noload.out
- $(common-objpfx)malloc/mtrace $(objpfx)noload.mtrace > $@
+$(objpfx)noload-mem.out: $(objpfx)noload.out
+ $(common-objpfx)malloc/mtrace $(objpfx)noload.mtrace > $@; \
+ $(evaluate-test)
noload-ENV = MALLOC_TRACE=$(objpfx)noload.mtrace
LDFLAGS-nodelete = -rdynamic
@@ -703,10 +736,13 @@ $(objpfx)lateglobal.out: $(objpfx)ltglobmod1.so $(objpfx)ltglobmod2.so
$(objpfx)tst-pathopt: $(libdl)
$(objpfx)tst-pathopt.out: tst-pathopt.sh $(objpfx)tst-pathopt \
$(objpfx)pathoptobj.so
- $(SHELL) $< $(common-objpfx) '$(test-wrapper-env)'
+ $(SHELL) $< $(common-objpfx) '$(test-wrapper-env)' \
+ '$(run-program-env)'; \
+ $(evaluate-test)
$(objpfx)tst-rtld-load-self.out: tst-rtld-load-self.sh $(objpfx)ld.so
- $(SHELL) $^ '$(test-wrapper)' '$(test-wrapper-env)' > $@
+ $(SHELL) $^ '$(test-wrapper)' '$(test-wrapper-env)' > $@; \
+ $(evaluate-test)
$(objpfx)initfirst: $(libdl)
$(objpfx)initfirst.out: $(objpfx)firstobj.so
@@ -843,52 +879,54 @@ $(objpfx)tst-execstack-needed: $(objpfx)tst-execstack-mod.so
LDFLAGS-tst-execstack-needed = -Wl,-z,noexecstack
LDFLAGS-tst-execstack-prog = -Wl,-z,execstack
+CFLAGS-tst-execstack-prog.c += -Wno-trampolines
+CFLAGS-tst-execstack-mod.c += -Wno-trampolines
endif
LDFLAGS-tst-array2 = $(no-as-needed)
LDFLAGS-tst-array5 = $(no-as-needed)
-$(objpfx)tst-array1.out: tst-array1.exp $(objpfx)tst-array1
- $(test-program-cmd) > $@
- cmp $@ tst-array1.exp > /dev/null
+$(objpfx)tst-array1-cmp.out: tst-array1.exp $(objpfx)tst-array1.out
+ cmp $^ > $@; \
+ $(evaluate-test)
-$(objpfx)tst-array1-static.out: tst-array1.exp $(objpfx)tst-array1-static
- $(test-program-cmd) > $@
- cmp $@ tst-array1.exp > /dev/null
+$(objpfx)tst-array1-static-cmp.out: tst-array1.exp \
+ $(objpfx)tst-array1-static.out
+ cmp $^ > $@; \
+ $(evaluate-test)
$(objpfx)tst-array2: $(objpfx)tst-array2dep.so
-$(objpfx)tst-array2.out: tst-array2.exp $(objpfx)tst-array2
- $(test-program-cmd) > $@
- cmp $@ tst-array2.exp > /dev/null
+$(objpfx)tst-array2-cmp.out: tst-array2.exp $(objpfx)tst-array2.out
+ cmp $^ > $@; \
+ $(evaluate-test)
-$(objpfx)tst-array3.out: tst-array1.exp $(objpfx)tst-array3
- $(test-program-cmd) > $@
- cmp $@ tst-array1.exp > /dev/null
+$(objpfx)tst-array3-cmp.out: tst-array1.exp $(objpfx)tst-array3.out
+ cmp $^ > $@; \
+ $(evaluate-test)
$(objpfx)tst-array4: $(libdl)
-$(objpfx)tst-array4.out: tst-array4.exp $(objpfx)tst-array4 \
- $(objpfx)tst-array2dep.so
- $(test-program-cmd) > $@
- cmp $@ tst-array4.exp > /dev/null
+$(objpfx)tst-array4.out: $(objpfx)tst-array2dep.so
+$(objpfx)tst-array4-cmp.out: tst-array4.exp $(objpfx)tst-array4.out
+ cmp $^ > $@; \
+ $(evaluate-test)
$(objpfx)tst-array5: $(objpfx)tst-array5dep.so
-$(objpfx)tst-array5.out: tst-array5.exp $(objpfx)tst-array5
- $(test-program-cmd) > $@
- cmp $@ tst-array5.exp > /dev/null
+$(objpfx)tst-array5-cmp.out: tst-array5.exp $(objpfx)tst-array5.out
+ cmp $^ > $@; \
+ $(evaluate-test)
-$(objpfx)tst-array5-static.out: tst-array5-static.exp \
- $(objpfx)tst-array5-static
- $(test-program-cmd) > $@
- cmp $@ tst-array5-static.exp > /dev/null
+$(objpfx)tst-array5-static-cmp.out: tst-array5-static.exp \
+ $(objpfx)tst-array5-static.out
+ cmp $^ > $@; \
+ $(evaluate-test)
CFLAGS-tst-pie1.c += $(pie-ccflag)
+CFLAGS-tst-pie2.c += $(pie-ccflag)
$(objpfx)tst-pie1: $(objpfx)tst-piemod1.so
ifeq (yes,$(build-shared))
-tests: $(objpfx)check-textrel.out $(objpfx)check-execstack.out
-
-all-built-dso := $(common-objpfx)libc.so \
+all-built-dso := $(common-objpfx)elf/ld.so $(common-objpfx)libc.so \
$(filter-out $(common-objpfx)linkobj/libc.so, \
$(sort $(wildcard $(addprefix $(common-objpfx), \
*/lib*.so \
@@ -903,7 +941,8 @@ common-generated += $(all-built-dso:$(common-objpfx)%=%.dyn)
$(objpfx)check-textrel.out: $(..)scripts/check-textrel.awk \
$(all-built-dso:=.dyn)
- LC_ALL=C $(AWK) -f $^ > $@
+ LC_ALL=C $(AWK) -f $^ > $@; \
+ $(evaluate-test)
generated += check-textrel.out
$(objpfx)execstack-default: $(first-word $(wildcard $(sysdirs:%=%/stackinfo.h)))
@@ -930,7 +969,8 @@ common-generated += $(all-built-dso:$(common-objpfx)%=%.phdr)
$(objpfx)check-execstack.out: $(..)scripts/check-execstack.awk \
$(objpfx)execstack-default \
$(all-built-dso:=.phdr)
- LC_ALL=C $(AWK) -f $^ > $@
+ LC_ALL=C $(AWK) -f $^ > $@; \
+ $(evaluate-test)
generated += check-execstack.out
$(objpfx)tst-dlmodcount: $(libdl)
@@ -943,16 +983,18 @@ $(all-built-dso:=.jmprel): %.jmprel: % Makefile
mv -f $@T $@
common-generated += $(all-built-dso:$(common-objpfx)%=%.jmprel)
-tests: $(objpfx)check-localplt.out
-
localplt-built-dso := $(addprefix $(common-objpfx),\
libc.so \
+ elf/ld.so \
math/libm.so \
rt/librt.so \
dlfcn/libdl.so \
resolv/libresolv.so \
crypt/libcrypt.so \
)
+ifeq ($(build-mathvec),yes)
+localplt-built-dso += $(addprefix $(common-objpfx), mathvec/libmvec.so)
+endif
ifeq ($(have-thread-library),yes)
localplt-built-dso += $(filter-out %_nonshared.a, $(shared-thread-library))
endif
@@ -965,7 +1007,8 @@ $(objpfx)check-localplt.out: $(..)scripts/check-localplt.awk \
localplt.data
LC_ALL=C $(AWK) -f $(filter-out $< %localplt.data,$^) | \
LC_ALL=C $(AWK) -f $< $(filter %localplt.data,$^) - \
- > $@
+ > $@; \
+ $(evaluate-test)
endif
$(objpfx)tst-dlopenrpathmod.so: $(libdl)
@@ -993,10 +1036,17 @@ $(objpfx)tst-dlmopen3.out: $(objpfx)tst-dlmopen1mod.so
$(objpfx)tst-audit1.out: $(objpfx)tst-auditmod1.so
tst-audit1-ENV = LD_AUDIT=$(objpfx)tst-auditmod1.so
-$(objpfx)tst-audit2.out: $(objpfx)tst-auditmod1.so
+$(objpfx)tst-audit2: $(libdl)
+$(objpfx)tst-audit2.out: $(objpfx)tst-auditmod1.so $(objpfx)tst-auditmod9b.so
+# Prevent GCC-5 from translating a malloc/memset pair into calloc
+CFLAGS-tst-audit2.c += -fno-builtin
tst-audit2-ENV = LD_AUDIT=$(objpfx)tst-auditmod1.so
-$(objpfx)tst-audit8: $(common-objpfx)math/libm.so
+$(objpfx)tst-audit9: $(libdl)
+$(objpfx)tst-audit9.out: $(objpfx)tst-auditmod9a.so $(objpfx)tst-auditmod9b.so
+tst-audit9-ENV = LD_AUDIT=$(objpfx)tst-auditmod9a.so
+
+$(objpfx)tst-audit8: $(libm)
$(objpfx)tst-audit8.out: $(objpfx)tst-auditmod1.so
tst-audit8-ENV = LD_AUDIT=$(objpfx)tst-auditmod1.so
@@ -1004,11 +1054,10 @@ $(objpfx)tst-global1: $(libdl)
$(objpfx)tst-global1.out: $(objpfx)testobj6.so $(objpfx)testobj2.so
$(objpfx)order2: $(libdl)
-$(objpfx)order2.out: $(objpfx)order2 $(objpfx)order2mod1.so \
- $(objpfx)order2mod2.so
- $(test-program-prefix) \
- $(objpfx)order2 > $@
- (echo "12345" | cmp $@ -) > /dev/null
+$(objpfx)order2.out: $(objpfx)order2mod1.so $(objpfx)order2mod2.so
+$(objpfx)order2-cmp.out: $(objpfx)order2.out
+ (echo "12345" | cmp $< -) > $@; \
+ $(evaluate-test)
$(objpfx)order2mod1.so: $(objpfx)order2mod4.so
$(objpfx)order2mod4.so: $(objpfx)order2mod3.so
$(objpfx)order2mod2.so: $(objpfx)order2mod3.so
@@ -1026,12 +1075,14 @@ CFLAGS-tst-ptrguard1-static.c = -DPTRGUARD_LOCAL
tst-ptrguard1-static-ARGS = --command "$(objpfx)tst-ptrguard1-static --child"
$(objpfx)tst-leaks1: $(libdl)
-$(objpfx)tst-leaks1-mem: $(objpfx)tst-leaks1.out
- $(common-objpfx)malloc/mtrace $(objpfx)tst-leaks1.mtrace > $@
+$(objpfx)tst-leaks1-mem.out: $(objpfx)tst-leaks1.out
+ $(common-objpfx)malloc/mtrace $(objpfx)tst-leaks1.mtrace > $@; \
+ $(evaluate-test)
$(objpfx)tst-leaks1-static: $(common-objpfx)dlfcn/libdl.a
-$(objpfx)tst-leaks1-static-mem: $(objpfx)tst-leaks1-static.out
- $(common-objpfx)malloc/mtrace $(objpfx)tst-leaks1-static.mtrace > $@
+$(objpfx)tst-leaks1-static-mem.out: $(objpfx)tst-leaks1-static.out
+ $(common-objpfx)malloc/mtrace $(objpfx)tst-leaks1-static.mtrace > $@; \
+ $(evaluate-test)
tst-leaks1-ENV = MALLOC_TRACE=$(objpfx)tst-leaks1.mtrace
tst-leaks1-static-ENV = MALLOC_TRACE=$(objpfx)tst-leaks1-static.mtrace
@@ -1039,6 +1090,7 @@ tst-leaks1-static-ENV = MALLOC_TRACE=$(objpfx)tst-leaks1-static.mtrace
$(objpfx)tst-addr1: $(libdl)
$(objpfx)tst-thrlock: $(libdl) $(shared-thread-library)
+$(objpfx)tst-dlopen-aout: $(libdl) $(shared-thread-library)
CFLAGS-ifuncmain1pic.c += $(pic-ccflag)
CFLAGS-ifuncmain1picstatic.c += $(pic-ccflag)
@@ -1104,10 +1156,17 @@ $(objpfx)tst-unique3.out: $(objpfx)tst-unique3lib2.so
$(objpfx)tst-unique4: $(objpfx)tst-unique4lib.so
-$(objpfx)tst-initorder.out: $(objpfx)tst-initorder
- $(test-program-prefix) \
- $< > $@
- cmp $@ tst-initorder.exp > /dev/null
+$(objpfx)tst-nodelete: $(libdl)
+$(objpfx)tst-nodelete.out: $(objpfx)tst-nodelete-uniquemod.so \
+ $(objpfx)tst-nodelete-rtldmod.so \
+ $(objpfx)tst-nodelete-zmod.so
+
+LDFLAGS-tst-nodelete = -rdynamic
+LDFLAGS-tst-nodelete-zmod.so = -Wl,--enable-new-dtags,-z,nodelete
+
+$(objpfx)tst-initorder-cmp.out: tst-initorder.exp $(objpfx)tst-initorder.out
+ cmp $^ > $@; \
+ $(evaluate-test)
$(objpfx)tst-initorder2: $(objpfx)tst-initorder2a.so $(objpfx)tst-initorder2d.so $(objpfx)tst-initorder2c.so
$(objpfx)tst-initorder2a.so: $(objpfx)tst-initorder2b.so
@@ -1124,10 +1183,9 @@ endef
object-suffixes-left := a b c d
include $(o-iterator)
-$(objpfx)tst-initorder2.out: $(objpfx)tst-initorder2
- $(test-program-prefix) \
- $< > $@
- cmp $@ tst-initorder2.exp > /dev/null
+$(objpfx)tst-initorder2-cmp.out: tst-initorder2.exp $(objpfx)tst-initorder2.out
+ cmp $^ > $@; \
+ $(evaluate-test)
$(objpfx)tst-relsort1: $(libdl)
$(objpfx)tst-relsort1mod1.so: $(libm) $(objpfx)tst-relsort1mod2.so
@@ -1135,16 +1193,15 @@ $(objpfx)tst-relsort1mod2.so: $(libm)
$(objpfx)tst-relsort1.out: $(objpfx)tst-relsort1mod1.so \
$(objpfx)tst-relsort1mod2.so
-ifeq ($(run-built-tests),yes)
-tests: $(objpfx)tst-unused-dep.out
-endif
-
$(objpfx)tst-unused-dep.out: $(objpfx)testobj1.so
$(test-wrapper-env) \
LD_TRACE_LOADED_OBJECTS=1 \
LD_DEBUG=unused \
LD_PRELOAD= \
- $(elf-objpfx)${rtld-installed-name} \
- --library-path $(rpath-link)$(patsubst %,:%,$(sysdep-library-path)) \
- $< > $@
- cmp $@ /dev/null > /dev/null
+ $(rtld-prefix) \
+ $< > $@; \
+ $(evaluate-test)
+
+$(objpfx)tst-unused-dep-cmp.out: $(objpfx)tst-unused-dep.out
+ cmp $< /dev/null > $@; \
+ $(evaluate-test)
diff --git a/elf/Versions b/elf/Versions
index 238399232d..23deda984f 100644
--- a/elf/Versions
+++ b/elf/Versions
@@ -12,6 +12,9 @@ libc {
dl_iterate_phdr;
}
%ifdef EXPORT_UNWIND_FIND_FDE
+ # Needed for SHLIB_COMPAT calls using this version.
+ GLIBC_2.2.5 {
+ }
GCC_3.0 {
__deregister_frame_info_bases; __register_frame_info_bases;
__register_frame_info_table_bases; _Unwind_Find_FDE;
diff --git a/elf/cache.c b/elf/cache.c
index 4cbf8d9a5c..bde7984924 100644
--- a/elf/cache.c
+++ b/elf/cache.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1999-2014 Free Software Foundation, Inc.
+/* Copyright (C) 1999-2015 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Andreas Jaeger <aj@suse.de>, 1999.
@@ -698,7 +698,9 @@ load_aux_cache (const char *aux_cache_name)
if (aux_cache == MAP_FAILED
|| aux_cache_size < sizeof (struct aux_cache_file)
|| memcmp (aux_cache->magic, AUX_CACHEMAGIC, sizeof AUX_CACHEMAGIC - 1)
- || aux_cache->nlibs >= aux_cache_size)
+ || aux_cache_size != (sizeof(struct aux_cache_file) +
+ aux_cache->nlibs * sizeof(struct aux_cache_file_entry) +
+ aux_cache->len_strings))
{
close (fd);
init_aux_cache ();
diff --git a/elf/chroot_canon.c b/elf/chroot_canon.c
index 0e3d1c419c..05a824103a 100644
--- a/elf/chroot_canon.c
+++ b/elf/chroot_canon.c
@@ -1,5 +1,5 @@
/* Return the canonical absolute name of a given file inside chroot.
- Copyright (C) 1996-2014 Free Software Foundation, Inc.
+ Copyright (C) 1996-2015 Free Software Foundation, Inc.
This file is part of the GNU C Library.
This program is free software; you can redistribute it and/or modify
diff --git a/elf/dl-addr.c b/elf/dl-addr.c
index ffb80fee9b..a025652c08 100644
--- a/elf/dl-addr.c
+++ b/elf/dl-addr.c
@@ -1,5 +1,5 @@
/* Locate the shared object symbol nearest a given address.
- Copyright (C) 1996-2014 Free Software Foundation, Inc.
+ Copyright (C) 1996-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
diff --git a/elf/dl-cache.c b/elf/dl-cache.c
index d36623f09e..dec49bc0f2 100644
--- a/elf/dl-cache.c
+++ b/elf/dl-cache.c
@@ -1,5 +1,5 @@
/* Support for reading /etc/ld.so.cache files written by Linux ldconfig.
- Copyright (C) 1996-2014 Free Software Foundation, Inc.
+ Copyright (C) 1996-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
@@ -65,7 +65,7 @@ do \
\
/* Actually compare the entry with the key. */ \
cmpres = _dl_cache_libcmp (name, cache_data + key); \
- if (__builtin_expect (cmpres == 0, 0)) \
+ if (__glibc_unlikely (cmpres == 0)) \
{ \
/* Found it. LEFT now marks the last entry for which we \
know the name is correct. */ \
@@ -174,9 +174,12 @@ _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. */
-
-const char *
+ the cache previously failed there will be no more attempts to load it.
+ The caller is responsible for freeing the returned string. The ld.so.cache
+ may be unmapped at any time by a completing recursive dlopen and
+ this function must take care that it does not return references to
+ any data in the mapping. */
+char *
internal_function
_dl_load_cache_lookup (const char *name)
{
@@ -187,7 +190,7 @@ _dl_load_cache_lookup (const char *name)
const char *best;
/* Print a message if the loading of libs is traced. */
- if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_LIBS, 0))
+ if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_LIBS))
_dl_debug_printf (" search cache=%s\n", LD_SO_CACHE);
if (cache == NULL)
@@ -289,7 +292,17 @@ _dl_load_cache_lookup (const char *name)
&& best != NULL)
_dl_debug_printf (" trying file=%s\n", best);
- return best;
+ if (best == NULL)
+ return NULL;
+
+ /* The double copy is *required* since malloc may be interposed
+ and call dlopen itself whose completion would unmap the data
+ we are accessing. Therefore we must make the copy of the
+ mapping data without using malloc. */
+ char *temp;
+ temp = alloca (strlen (best) + 1);
+ strcpy (temp, best);
+ return strdup (temp);
}
#ifndef MAP_COPY
diff --git a/elf/dl-caller.c b/elf/dl-caller.c
index 97fa062dd0..bfef108be2 100644
--- a/elf/dl-caller.c
+++ b/elf/dl-caller.c
@@ -1,5 +1,5 @@
/* Check whether caller comes from the right place.
- Copyright (C) 2004-2014 Free Software Foundation, Inc.
+ Copyright (C) 2004-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
diff --git a/elf/dl-close.c b/elf/dl-close.c
index 5bf1de7d28..910527746e 100644
--- a/elf/dl-close.c
+++ b/elf/dl-close.c
@@ -1,5 +1,5 @@
/* Close a shared object opened by `_dl_open'.
- Copyright (C) 1996-2014 Free Software Foundation, Inc.
+ Copyright (C) 1996-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
@@ -33,6 +33,8 @@
#include <tls.h>
#include <stap-probe.h>
+#include <dl-unmap-segments.h>
+
/* Type of the constructor functions. */
typedef void (*fini_t) (void);
@@ -73,7 +75,7 @@ remove_slotinfo (size_t idx, struct dtv_slotinfo_list *listp, size_t disp,
/* The entry might still be in its unused state if we are closing an
object that wasn't fully set up. */
- if (__builtin_expect (old_map != NULL, 1))
+ if (__glibc_likely (old_map != NULL))
{
assert (old_map->l_tls_modid == idx);
@@ -106,7 +108,7 @@ remove_slotinfo (size_t idx, struct dtv_slotinfo_list *listp, size_t disp,
void
-_dl_close_worker (struct link_map *map)
+_dl_close_worker (struct link_map *map, bool force)
{
/* One less direct use. */
--map->l_direct_opencount;
@@ -123,7 +125,7 @@ _dl_close_worker (struct link_map *map)
dl_close_state = rerun;
/* There are still references to this object. Do nothing more. */
- if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_FILES, 0))
+ if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES))
_dl_debug_printf ("\nclosing file=%s; direct_opencount=%u\n",
map->l_name, map->l_direct_opencount);
@@ -150,6 +152,14 @@ _dl_close_worker (struct link_map *map)
l->l_idx = idx;
maps[idx] = l;
++idx;
+
+ /* Clear DF_1_NODELETE to force object deletion. We don't need to touch
+ l_tls_dtor_count because forced object deletion only happens when an
+ error occurs during object load. Destructor registration for TLS
+ non-POD objects should not have happened till then for this
+ object. */
+ if (force)
+ l->l_flags_1 &= ~DF_1_NODELETE;
}
assert (idx == nloaded);
@@ -171,6 +181,9 @@ _dl_close_worker (struct link_map *map)
if (l->l_type == lt_loaded
&& l->l_direct_opencount == 0
&& (l->l_flags_1 & DF_1_NODELETE) == 0
+ /* See CONCURRENCY NOTES in cxa_thread_atexit_impl.c to know why
+ acquire is sufficient and correct. */
+ && atomic_load_acquire (&l->l_tls_dtor_count) == 0
&& !used[done_index])
continue;
@@ -280,7 +293,7 @@ _dl_close_worker (struct link_map *map)
#ifdef SHARED
/* Auditing checkpoint: we remove an object. */
- if (__builtin_expect (do_audit, 0))
+ if (__glibc_unlikely (do_audit))
{
struct audit_ifaces *afct = GLRO(dl_audit);
for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
@@ -452,7 +465,7 @@ _dl_close_worker (struct link_map *map)
#ifdef SHARED
/* Auditing checkpoint: we will start deleting objects. */
- if (__builtin_expect (do_audit, 0))
+ if (__glibc_unlikely (do_audit))
{
struct link_map *head = ns->_ns_loaded;
struct audit_ifaces *afct = GLRO(dl_audit);
@@ -536,7 +549,7 @@ _dl_close_worker (struct link_map *map)
object. We can unmap it. */
/* Remove the object from the dtv slotinfo array if it uses TLS. */
- if (__builtin_expect (imap->l_tls_blocksize > 0, 0))
+ if (__glibc_unlikely (imap->l_tls_blocksize > 0))
{
any_tls = true;
@@ -633,15 +646,47 @@ _dl_close_worker (struct link_map *map)
}
}
+ /* Reset unique symbols if forced. */
+ if (force)
+ {
+ struct unique_sym_table *tab = &ns->_ns_unique_sym_table;
+ __rtld_lock_lock_recursive (tab->lock);
+ struct unique_sym *entries = tab->entries;
+ if (entries != NULL)
+ {
+ size_t idx, size = tab->size;
+ for (idx = 0; idx < size; ++idx)
+ {
+ /* Clear unique symbol entries that belong to this
+ object. */
+ if (entries[idx].name != NULL
+ && entries[idx].map == imap)
+ {
+ entries[idx].name = NULL;
+ entries[idx].hashval = 0;
+ tab->n_elements--;
+ }
+ }
+ }
+ __rtld_lock_unlock_recursive (tab->lock);
+ }
+
/* We can unmap all the maps at once. We determined the
start address and length when we loaded the object and
the `munmap' call does the rest. */
DL_UNMAP (imap);
/* Finally, unlink the data structure and free it. */
- if (imap->l_prev != NULL)
- imap->l_prev->l_next = imap->l_next;
- else
+#if DL_NNS == 1
+ /* The assert in the (imap->l_prev == NULL) case gives
+ the compiler license to warn that NS points outside
+ the dl_ns array bounds in that case (as nsid != LM_ID_BASE
+ is tantamount to nsid >= DL_NNS). That should be impossible
+ in this configuration, so just assert about it instead. */
+ assert (nsid == LM_ID_BASE);
+ assert (imap->l_prev != NULL);
+#else
+ if (imap->l_prev == NULL)
{
assert (nsid != LM_ID_BASE);
ns->_ns_loaded = imap->l_next;
@@ -650,6 +695,9 @@ _dl_close_worker (struct link_map *map)
we leave for debuggers to examine. */
r->r_map = (void *) ns->_ns_loaded;
}
+ else
+#endif
+ imap->l_prev->l_next = imap->l_next;
--ns->_ns_nloaded;
if (imap->l_next != NULL)
@@ -662,7 +710,7 @@ _dl_close_worker (struct link_map *map)
free (imap->l_reldeps);
/* Print debugging message. */
- if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_FILES, 0))
+ if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES))
_dl_debug_printf ("\nfile=%s [%lu]; destroying link map\n",
imap->l_name, imap->l_ns);
@@ -704,7 +752,7 @@ _dl_close_worker (struct link_map *map)
/* If we removed any object which uses TLS bump the generation counter. */
if (any_tls)
{
- if (__builtin_expect (++GL(dl_tls_generation) == 0, 0))
+ if (__glibc_unlikely (++GL(dl_tls_generation) == 0))
_dl_fatal_printf ("TLS generation counter wrapped! Please report as described in "REPORT_BUGS_TO".\n");
if (tls_free_end == GL(dl_tls_static_used))
@@ -713,7 +761,7 @@ _dl_close_worker (struct link_map *map)
#ifdef SHARED
/* Auditing checkpoint: we have deleted all objects. */
- if (__builtin_expect (do_audit, 0))
+ if (__glibc_unlikely (do_audit))
{
struct link_map *head = ns->_ns_loaded;
/* Do not call the functions for any auditing object. */
@@ -757,7 +805,7 @@ _dl_close (void *_map)
struct link_map *map = _map;
/* First see whether we can remove the object at all. */
- if (__builtin_expect (map->l_flags_1 & DF_1_NODELETE, 0))
+ if (__glibc_unlikely (map->l_flags_1 & DF_1_NODELETE))
{
assert (map->l_init_called);
/* Nope. Do nothing. */
@@ -770,7 +818,7 @@ _dl_close (void *_map)
/* Acquire the lock. */
__rtld_lock_lock_recursive (GL(dl_load_lock));
- _dl_close_worker (map);
+ _dl_close_worker (map, false);
__rtld_lock_unlock_recursive (GL(dl_load_lock));
}
diff --git a/elf/dl-conflict.c b/elf/dl-conflict.c
index 8034077567..47a946e413 100644
--- a/elf/dl-conflict.c
+++ b/elf/dl-conflict.c
@@ -1,5 +1,5 @@
/* Resolve conflicts against already prelinked libraries.
- Copyright (C) 2001-2014 Free Software Foundation, Inc.
+ Copyright (C) 2001-2015 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Jakub Jelinek <jakub@redhat.com>, 2001.
@@ -32,7 +32,7 @@ _dl_resolve_conflicts (struct link_map *l, ElfW(Rela) *conflict,
ElfW(Rela) *conflictend)
{
#if ! ELF_MACHINE_NO_RELA
- if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_RELOC, 0))
+ if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_RELOC))
_dl_debug_printf ("\nconflict processing: %s\n", DSO_FILENAME (l->l_name));
{
diff --git a/elf/dl-debug.c b/elf/dl-debug.c
index 4e7c5935b4..e32a5a64e4 100644
--- a/elf/dl-debug.c
+++ b/elf/dl-debug.c
@@ -1,5 +1,5 @@
/* Communicate dynamic linker state to the debugger at runtime.
- Copyright (C) 1996-2014 Free Software Foundation, Inc.
+ Copyright (C) 1996-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
diff --git a/elf/dl-deps.c b/elf/dl-deps.c
index 20c294e5b8..eee146a242 100644
--- a/elf/dl-deps.c
+++ b/elf/dl-deps.c
@@ -1,5 +1,5 @@
/* Load the dependencies of a mapped object.
- Copyright (C) 1996-2014 Free Software Foundation, Inc.
+ Copyright (C) 1996-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
@@ -108,7 +108,7 @@ struct list
char *__newp; \
\
/* DST must not appear in SUID/SGID programs. */ \
- if (INTUSE(__libc_enable_secure)) \
+ if (__libc_enable_secure) \
_dl_signal_error (0, __str, NULL, N_("\
DST not allowed in SUID/SGID programs")); \
\
@@ -127,7 +127,7 @@ empty dynamic string token substitution")); \
else \
{ \
/* This is for DT_AUXILIARY. */ \
- if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_LIBS, 0))\
+ if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_LIBS)) \
_dl_debug_printf (N_("\
cannot load auxiliary `%s' because of empty dynamic string token " \
"substitution\n"), __str); \
@@ -138,6 +138,19 @@ cannot load auxiliary `%s' because of empty dynamic string token " \
\
__result; })
+static void
+preload (struct list *known, unsigned int *nlist, struct link_map *map)
+{
+ known[*nlist].done = 0;
+ known[*nlist].map = map;
+ known[*nlist].next = &known[*nlist + 1];
+
+ ++*nlist;
+ /* We use `l_reserved' as a mark bit to detect objects we have
+ already put in the search list and avoid adding duplicate
+ elements later in the list. */
+ map->l_reserved = 1;
+}
void
internal_function
@@ -155,28 +168,15 @@ _dl_map_object_deps (struct link_map *map,
const char *errstring;
const char *objname;
- void preload (struct link_map *map)
- {
- known[nlist].done = 0;
- known[nlist].map = map;
- known[nlist].next = &known[nlist + 1];
-
- ++nlist;
- /* We use `l_reserved' as a mark bit to detect objects we have
- already put in the search list and avoid adding duplicate
- elements later in the list. */
- map->l_reserved = 1;
- }
-
/* No loaded object so far. */
nlist = 0;
/* First load MAP itself. */
- preload (map);
+ preload (known, &nlist, map);
/* Add the preloaded items after MAP but before any of its dependencies. */
for (i = 0; i < npreloads; ++i)
- preload (preloads[i]);
+ preload (known, &nlist, preloads[i]);
/* Terminate the lists. */
known[nlist - 1].next = NULL;
@@ -253,7 +253,7 @@ _dl_map_object_deps (struct link_map *map,
bool malloced;
int err = _dl_catch_error (&objname, &errstring, &malloced,
openaux, &args);
- if (__builtin_expect (errstring != NULL, 0))
+ if (__glibc_unlikely (errstring != NULL))
{
char *new_errstring = strdupa (errstring);
objname = strdupa (objname);
@@ -302,22 +302,24 @@ _dl_map_object_deps (struct link_map *map,
/* Store the tag in the argument structure. */
args.name = name;
- if (d->d_tag == DT_AUXILIARY)
+ /* Say that we are about to load an auxiliary library. */
+ if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_LIBS,
+ 0))
+ _dl_debug_printf ("load auxiliary object=%s"
+ " requested by file=%s\n",
+ name,
+ DSO_FILENAME (l->l_name));
+
+ /* We must be prepared that the addressed shared
+ object is not available. For filter objects the dependency
+ must be available. */
+ bool malloced;
+ int err = _dl_catch_error (&objname, &errstring, &malloced,
+ openaux, &args);
+
+ if (__glibc_unlikely (errstring != NULL))
{
- /* Say that we are about to load an auxiliary library. */
- if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_LIBS,
- 0))
- _dl_debug_printf ("load auxiliary object=%s"
- " requested by file=%s\n",
- name,
- DSO_FILENAME (l->l_name));
-
- /* We must be prepared that the addressed shared
- object is not available. */
- bool malloced;
- (void) _dl_catch_error (&objname, &errstring, &malloced,
- openaux, &args);
- if (__builtin_expect (errstring != NULL, 0))
+ if (d->d_tag == DT_AUXILIARY)
{
/* We are not interested in the error message. */
assert (errstring != NULL);
@@ -327,23 +329,9 @@ _dl_map_object_deps (struct link_map *map,
/* Simply ignore this error and continue the work. */
continue;
}
- }
- else
- {
- /* Say that we are about to load an auxiliary library. */
- if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_LIBS,
- 0))
- _dl_debug_printf ("load filtered object=%s"
- " requested by file=%s\n",
- name,
- DSO_FILENAME (l->l_name));
-
- /* For filter objects the dependency must be available. */
- bool malloced;
- int err = _dl_catch_error (&objname, &errstring, &malloced,
- openaux, &args);
- if (__builtin_expect (errstring != NULL, 0))
+ else
{
+
char *new_errstring = strdupa (errstring);
objname = strdupa (objname);
if (malloced)
@@ -622,7 +610,7 @@ Filters not supported with LD_TRACE_PRELINKING"));
itself will always be initialize last. */
memcpy (l_initfini, map->l_searchlist.r_list,
nlist * sizeof (struct link_map *));
- if (__builtin_expect (nlist > 1, 1))
+ if (__glibc_likely (nlist > 1))
{
/* We can skip looking for the binary itself which is at the front
of the search list. */
@@ -645,7 +633,7 @@ Filters not supported with LD_TRACE_PRELINKING"));
if (runp != NULL)
/* Look through the dependencies of the object. */
while (*runp != NULL)
- if (__builtin_expect (*runp++ == thisp, 0))
+ if (__glibc_unlikely (*runp++ == thisp))
{
/* Move the current object to the back past the last
object with it as the dependency. */
diff --git a/elf/dl-dst.h b/elf/dl-dst.h
index a00e921583..817b415c77 100644
--- a/elf/dl-dst.h
+++ b/elf/dl-dst.h
@@ -1,5 +1,5 @@
/* Handling of dynamic sring tokens.
- Copyright (C) 1999-2014 Free Software Foundation, Inc.
+ Copyright (C) 1999-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
@@ -25,7 +25,7 @@
size_t __cnt = 0; \
const char *__sf = strchr (name, '$'); \
\
- if (__builtin_expect (__sf != NULL, 0)) \
+ if (__glibc_unlikely (__sf != NULL)) \
__cnt = _dl_dst_count (__sf, is_path); \
\
__cnt; })
diff --git a/elf/dl-environ.c b/elf/dl-environ.c
index afcd11de90..d3463544f4 100644
--- a/elf/dl-environ.c
+++ b/elf/dl-environ.c
@@ -1,5 +1,5 @@
/* Environment handling for dynamic loader.
- Copyright (C) 1995-2014 Free Software Foundation, Inc.
+ Copyright (C) 1995-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
diff --git a/elf/dl-error.c b/elf/dl-error.c
index 60c2a7330c..0fc3fd846e 100644
--- a/elf/dl-error.c
+++ b/elf/dl-error.c
@@ -1,5 +1,5 @@
/* Error handling for runtime dynamic linker.
- Copyright (C) 1995-2014 Free Software Foundation, Inc.
+ Copyright (C) 1995-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
diff --git a/elf/dl-execstack.c b/elf/dl-execstack.c
index 5dfbb8e366..dd3eb3d671 100644
--- a/elf/dl-execstack.c
+++ b/elf/dl-execstack.c
@@ -1,5 +1,5 @@
/* Stack executability handling for GNU dynamic linker. Stub version.
- Copyright (C) 2003-2014 Free Software Foundation, Inc.
+ Copyright (C) 2003-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
diff --git a/elf/dl-fini.c b/elf/dl-fini.c
index 05bbd68aee..6cfe6519c4 100644
--- a/elf/dl-fini.c
+++ b/elf/dl-fini.c
@@ -1,5 +1,5 @@
/* Call the termination functions of loaded shared objects.
- Copyright (C) 1995-2014 Free Software Foundation, Inc.
+ Copyright (C) 1995-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
@@ -60,7 +60,7 @@ _dl_sort_fini (struct link_map **maps, size_t nmaps, char *used, Lmid_t ns)
if (runp != NULL)
/* Look through the dependencies of the object. */
while (*runp != NULL)
- if (__builtin_expect (*runp++ == thisp, 0))
+ if (__glibc_unlikely (*runp++ == thisp))
{
move:
/* Move the current object to the back past the last
@@ -90,21 +90,21 @@ _dl_sort_fini (struct link_map **maps, size_t nmaps, char *used, Lmid_t ns)
goto next;
}
- if (__builtin_expect (maps[k]->l_reldeps != NULL, 0))
+ if (__glibc_unlikely (maps[k]->l_reldeps != NULL))
{
unsigned int m = maps[k]->l_reldeps->act;
struct link_map **relmaps = &maps[k]->l_reldeps->list[0];
/* Look through the relocation dependencies of the object. */
while (m-- > 0)
- if (__builtin_expect (relmaps[m] == thisp, 0))
+ if (__glibc_unlikely (relmaps[m] == thisp))
{
/* If a cycle exists with a link time dependency,
preserve the latter. */
struct link_map **runp = thisp->l_initfini;
if (runp != NULL)
while (*runp != NULL)
- if (__builtin_expect (*runp++ == maps[k], 0))
+ if (__glibc_unlikely (*runp++ == maps[k]))
goto ignore;
goto move;
}
@@ -286,7 +286,7 @@ _dl_fini (void)
goto again;
}
- if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_STATISTICS, 0))
+ if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_STATISTICS))
_dl_debug_printf ("\nruntime linker statistics:\n"
" final number of relocations: %lu\n"
"final number of relocations from cache: %lu\n",
diff --git a/elf/dl-fptr.c b/elf/dl-fptr.c
index 8088db3d4f..0137eec05c 100644
--- a/elf/dl-fptr.c
+++ b/elf/dl-fptr.c
@@ -1,5 +1,5 @@
/* Manage function descriptors. Generic version.
- Copyright (C) 1999-2014 Free Software Foundation, Inc.
+ Copyright (C) 1999-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
@@ -25,6 +25,7 @@
#include <ldsodefs.h>
#include <elf/dynamic-link.h>
#include <dl-fptr.h>
+#include <dl-unmap-segments.h>
#include <atomic.h>
#ifndef ELF_MACHINE_BOOT_FPTR_TABLE_LEN
@@ -209,7 +210,7 @@ _dl_make_fptr (struct link_map *map, const ElfW(Sym) *sym,
Elf_Symndx symidx;
struct local *l;
- if (__builtin_expect (ftab == NULL, 0))
+ if (__glibc_unlikely (ftab == NULL))
ftab = make_fptr_table (map);
symtab = (const void *) D_PTR (map, l_info[DT_SYMTAB]);
@@ -269,8 +270,7 @@ _dl_unmap (struct link_map *map)
struct fdesc *head = NULL, *tail = NULL;
size_t i;
- __munmap ((void *) map->l_map_start,
- map->l_map_end - map->l_map_start);
+ _dl_unmap_segments (map);
if (ftab == NULL)
return;
diff --git a/elf/dl-hwcaps.c b/elf/dl-hwcaps.c
index 86d9e9cd6d..39328edd48 100644
--- a/elf/dl-hwcaps.c
+++ b/elf/dl-hwcaps.c
@@ -1,5 +1,5 @@
/* Hardware capability support for run-time dynamic loader.
- Copyright (C) 2012-2014 Free Software Foundation, Inc.
+ Copyright (C) 2012-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
@@ -133,7 +133,7 @@ _dl_important_hwcaps (const char *platform, size_t platform_len, size_t *sz,
len = strlen (p);
/* Skip entries that are not enabled in the mask word. */
- if (__builtin_expect (mask & ((ElfW(Word)) 1 << bit), 1))
+ if (__glibc_likely (mask & ((ElfW(Word)) 1 << bit)))
{
temp[m].str = p;
temp[m].len = len;
diff --git a/elf/dl-init.c b/elf/dl-init.c
index 28a6ff6d8a..2f85731ff3 100644
--- a/elf/dl-init.c
+++ b/elf/dl-init.c
@@ -1,5 +1,5 @@
/* Run initializers for newly loaded objects.
- Copyright (C) 1995-2014 Free Software Foundation, Inc.
+ Copyright (C) 1995-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
@@ -23,12 +23,6 @@
/* Type of the initializer. */
typedef void (*init_t) (int, char **, char **);
-#ifndef HAVE_INLINED_SYSCALLS
-/* Flag, nonzero during startup phase. */
-extern int _dl_starting_up;
-extern int _dl_starting_up_internal attribute_hidden;
-#endif
-
static void
call_init (struct link_map *l, int argc, char **argv, char **env)
@@ -52,7 +46,7 @@ call_init (struct link_map *l, int argc, char **argv, char **env)
return;
/* Print a debug message if wanted. */
- if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_IMPCALLS, 0))
+ if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_IMPCALLS))
_dl_debug_printf ("\ncalling init: %s\n\n",
DSO_FILENAME (l->l_name));
@@ -88,7 +82,7 @@ _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;
- if (__builtin_expect (GL(dl_initfirst) != NULL, 0))
+ if (__glibc_unlikely (GL(dl_initfirst) != NULL))
{
call_init (GL(dl_initfirst), argc, argv, env);
GL(dl_initfirst) = NULL;
@@ -102,7 +96,7 @@ _dl_init (struct link_map *main_map, int argc, char **argv, char **env)
ElfW(Addr) *addrs;
unsigned int cnt;
- if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_IMPCALLS, 0))
+ if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_IMPCALLS))
_dl_debug_printf ("\ncalling preinit: %s\n\n",
DSO_FILENAME (main_map->l_name));
@@ -127,7 +121,6 @@ _dl_init (struct link_map *main_map, int argc, char **argv, char **env)
#ifndef HAVE_INLINED_SYSCALLS
/* Finished starting up. */
- INTUSE(_dl_starting_up) = 0;
+ _dl_starting_up = 0;
#endif
}
-INTDEF (_dl_init)
diff --git a/elf/dl-iteratephdr.c b/elf/dl-iteratephdr.c
index 6572ec3a33..906c9ce6f5 100644
--- a/elf/dl-iteratephdr.c
+++ b/elf/dl-iteratephdr.c
@@ -1,5 +1,5 @@
/* Get loaded objects program headers.
- Copyright (C) 2001-2014 Free Software Foundation, Inc.
+ Copyright (C) 2001-2015 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Jakub Jelinek <jakub@redhat.com>, 2001.
diff --git a/elf/dl-libc.c b/elf/dl-libc.c
index ceac3caeb2..df2732425a 100644
--- a/elf/dl-libc.c
+++ b/elf/dl-libc.c
@@ -1,5 +1,5 @@
/* Handle loading and unloading shared objects for internal libc purposes.
- Copyright (C) 1999-2014 Free Software Foundation, Inc.
+ Copyright (C) 1999-2015 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Zack Weinberg <zack@rabi.columbia.edu>, 1999.
@@ -158,7 +158,7 @@ __libc_dlopen_mode (const char *name, int mode)
args.caller_dlopen = RETURN_ADDRESS (0);
#ifdef SHARED
- if (__builtin_expect (_dl_open_hook != NULL, 0))
+ if (__glibc_unlikely (_dl_open_hook != NULL))
return _dl_open_hook->dlopen_mode (name, mode);
return (dlerror_run (do_dlopen, &args) ? NULL : (void *) args.map);
#else
@@ -204,7 +204,7 @@ __libc_dlsym (void *map, const char *name)
args.name = name;
#ifdef SHARED
- if (__builtin_expect (_dl_open_hook != NULL, 0))
+ if (__glibc_unlikely (_dl_open_hook != NULL))
return _dl_open_hook->dlsym (map, name);
#endif
return (dlerror_run (do_dlsym, &args) ? NULL
@@ -216,7 +216,7 @@ int
__libc_dlclose (void *map)
{
#ifdef SHARED
- if (__builtin_expect (_dl_open_hook != NULL, 0))
+ if (__glibc_unlikely (_dl_open_hook != NULL))
return _dl_open_hook->dlclose (map);
#endif
return dlerror_run (do_dlclose, map);
diff --git a/elf/dl-load.c b/elf/dl-load.c
index 1be7a3ca96..0c052e449a 100644
--- a/elf/dl-load.c
+++ b/elf/dl-load.c
@@ -1,5 +1,5 @@
/* Map in a shared object's segments from the file.
- Copyright (C) 1995-2014 Free Software Foundation, Inc.
+ Copyright (C) 1995-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
@@ -38,39 +38,10 @@
#include <stap-probe.h>
#include <dl-dst.h>
-
-/* On some systems, no flag bits are given to specify file mapping. */
-#ifndef MAP_FILE
-# define MAP_FILE 0
-#endif
-
-/* The right way to map in the shared library files is MAP_COPY, which
- makes a virtual copy of the data at the time of the mmap call; this
- guarantees the mapped pages will be consistent even if the file is
- overwritten. Some losing VM systems like Linux's lack MAP_COPY. All we
- get is MAP_PRIVATE, which copies each page when it is modified; this
- means if the file is overwritten, we may at some point get some pages
- from the new version after starting with pages from the old version.
-
- To make up for the lack and avoid the overwriting problem,
- what Linux does have is MAP_DENYWRITE. This prevents anyone
- from modifying the file while we have it mapped. */
-#ifndef MAP_COPY
-# ifdef MAP_DENYWRITE
-# define MAP_COPY (MAP_PRIVATE | MAP_DENYWRITE)
-# else
-# define MAP_COPY MAP_PRIVATE
-# endif
-#endif
-
-/* Some systems link their relocatable objects for another base address
- than 0. We want to know the base address for these such that we can
- subtract this address from the segment addresses during mapping.
- This results in a more efficient address space usage. Defaults to
- zero for almost all systems. */
-#ifndef MAP_BASE_ADDR
-# define MAP_BASE_ADDR(l) 0
-#endif
+#include <dl-load.h>
+#include <dl-map-segments.h>
+#include <dl-unmap-segments.h>
+#include <dl-machine-reject-phdr.h>
#include <endian.h>
@@ -85,18 +56,6 @@
#define STRING(x) __STRING (x)
-/* Handle situations where we have a preferred location in memory for
- the shared objects. */
-#ifdef ELF_PREFERRED_ADDRESS_DATA
-ELF_PREFERRED_ADDRESS_DATA;
-#endif
-#ifndef ELF_PREFERRED_ADDRESS
-# define ELF_PREFERRED_ADDRESS(loader, maplength, mapstartpref) (mapstartpref)
-#endif
-#ifndef ELF_FIXED_ADDRESS
-# define ELF_FIXED_ADDRESS(loader, mapstart) ((void) 0)
-#endif
-
int __stack_prot attribute_hidden attribute_relro
#if _STACK_GROWS_DOWN && defined PROT_GROWSDOWN
@@ -154,20 +113,6 @@ static const size_t system_dirs_len[] =
(sizeof (system_dirs_len) / sizeof (system_dirs_len[0]))
-/* Local version of `strdup' function. */
-static char *
-local_strdup (const char *s)
-{
- size_t len = strlen (s) + 1;
- void *new = malloc (len);
-
- if (new == NULL)
- return NULL;
-
- return (char *) memcpy (new, s, len);
-}
-
-
static bool
is_trusted_path (const char *path, size_t len)
{
@@ -280,7 +225,7 @@ is_dst (const char *start, const char *name, const char *str,
&& (!is_path || name[len] != ':'))
return 0;
- if (__builtin_expect (secure, 0)
+ if (__glibc_unlikely (secure)
&& ((name[len] != '\0' && name[len] != '/'
&& (!is_path || name[len] != ':'))
|| (name != start + 1 && (!is_path || name[-2] != ':'))))
@@ -304,7 +249,7 @@ _dl_dst_count (const char *name, int is_path)
is $ORIGIN alone) and it must always appear first in path. */
++name;
if ((len = is_dst (start, name, "ORIGIN", is_path,
- INTUSE(__libc_enable_secure))) != 0
+ __libc_enable_secure)) != 0
|| (len = is_dst (start, name, "PLATFORM", is_path, 0)) != 0
|| (len = is_dst (start, name, "LIB", is_path, 0)) != 0)
++cnt;
@@ -333,17 +278,17 @@ _dl_dst_substitute (struct link_map *l, const char *name, char *result,
do
{
- if (__builtin_expect (*name == '$', 0))
+ if (__glibc_unlikely (*name == '$'))
{
const char *repl = NULL;
size_t len;
++name;
if ((len = is_dst (start, name, "ORIGIN", is_path,
- INTUSE(__libc_enable_secure))) != 0)
+ __libc_enable_secure)) != 0)
{
repl = l->l_origin;
- check_for_trusted = (INTUSE(__libc_enable_secure)
+ check_for_trusted = (__libc_enable_secure
&& l->l_type == lt_executable);
}
else if ((len = is_dst (start, name, "PLATFORM", is_path, 0)) != 0)
@@ -381,7 +326,7 @@ _dl_dst_substitute (struct link_map *l, const char *name, char *result,
/* In SUID/SGID programs, after $ORIGIN expansion the
normalized path must be rooted in one of the trusted
directories. */
- if (__builtin_expect (check_for_trusted, false)
+ if (__glibc_unlikely (check_for_trusted)
&& !is_trusted_path_normalize (last_elem, wp - last_elem))
wp = last_elem;
else
@@ -395,7 +340,7 @@ _dl_dst_substitute (struct link_map *l, const char *name, char *result,
/* In SUID/SGID programs, after $ORIGIN expansion the normalized
path must be rooted in one of the trusted directories. */
- if (__builtin_expect (check_for_trusted, false)
+ if (__glibc_unlikely (check_for_trusted)
&& !is_trusted_path_normalize (last_elem, wp - last_elem))
wp = last_elem;
@@ -425,8 +370,8 @@ expand_dynamic_string_token (struct link_map *l, const char *s, int is_path)
cnt = DL_DST_COUNT (s, is_path);
/* If we do not have to replace anything simply copy the string. */
- if (__builtin_expect (cnt, 0) == 0)
- return local_strdup (s);
+ if (__glibc_likely (cnt == 0))
+ return __strdup (s);
/* Determine the length of the substituted string. */
total = DL_DST_REQUIRED (l, s, strlen (s), cnt);
@@ -513,7 +458,7 @@ fillin_rpath (char *rpath, struct r_search_path_elem **result, const char *sep,
cp[len++] = '/';
/* Make sure we don't use untrusted directories if we run SUID. */
- if (__builtin_expect (check_trusted, 0) && !is_trusted_path (cp, len))
+ if (__glibc_unlikely (check_trusted) && !is_trusted_path (cp, len))
{
free (to_free);
continue;
@@ -565,7 +510,7 @@ fillin_rpath (char *rpath, struct r_search_path_elem **result, const char *sep,
dirp->status[cnt] = init_val;
dirp->what = what;
- if (__builtin_expect (where != NULL, 1))
+ if (__glibc_likely (where != NULL))
dirp->where = memcpy ((char *) dirp + sizeof (*dirp) + len + 1
+ (ncapstr * sizeof (enum r_dir_status)),
where, where_len);
@@ -604,8 +549,8 @@ decompose_rpath (struct r_search_path_struct *sps,
/* First see whether we must forget the RUNPATH and RPATH from this
object. */
- if (__builtin_expect (GLRO(dl_inhibit_rpath) != NULL, 0)
- && !INTUSE(__libc_enable_secure))
+ if (__glibc_unlikely (GLRO(dl_inhibit_rpath) != NULL)
+ && !__libc_enable_secure)
{
const char *inhp = GLRO(dl_inhibit_rpath);
@@ -635,7 +580,7 @@ decompose_rpath (struct r_search_path_struct *sps,
}
/* Make a writable copy. */
- copy = local_strdup (rpath);
+ copy = __strdup (rpath);
if (copy == NULL)
{
errstring = N_("cannot create RUNPATH/RPATH copy");
@@ -836,7 +781,7 @@ _dl_init_paths (const char *llp)
#ifdef SHARED
/* Expand DSTs. */
size_t cnt = DL_DST_COUNT (llp, 1);
- if (__builtin_expect (cnt == 0, 1))
+ if (__glibc_likely (cnt == 0))
llp_tmp = strdupa (llp);
else
{
@@ -870,7 +815,7 @@ _dl_init_paths (const char *llp)
}
(void) fillin_rpath (llp_tmp, env_path_list.dirs, ":;",
- INTUSE(__libc_enable_secure), "LD_LIBRARY_PATH",
+ __libc_enable_secure, "LD_LIBRARY_PATH",
NULL, l);
if (env_path_list.dirs[0] == NULL)
@@ -927,7 +872,6 @@ _dl_map_object_from_fd (const char *name, int fd, struct filebuf *fbp,
const ElfW(Phdr) *ph;
size_t maplength;
int type;
- struct stat64 st;
/* Initialize to keep the compiler happy. */
const char *errstring = NULL;
int errval = 0;
@@ -935,7 +879,8 @@ _dl_map_object_from_fd (const char *name, int fd, struct filebuf *fbp,
bool make_consistent = false;
/* Get file information. */
- if (__builtin_expect (__fxstat64 (_STAT_VER, fd, &st) < 0, 0))
+ struct r_file_id id;
+ if (__glibc_unlikely (!_dl_get_file_id (fd, &id)))
{
errstring = N_("cannot stat shared object");
call_lose_errno:
@@ -946,8 +891,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)
+ for (l = GL(dl_ns)[nsid]._ns_loaded; l != NULL; l = l->l_next)
+ if (!l->l_removed && _dl_file_id_match_p (&l->l_file_id, &id))
{
/* The object is already loaded.
Just bump its reference count and return it. */
@@ -964,9 +909,8 @@ _dl_map_object_from_fd (const char *name, int fd, struct filebuf *fbp,
#ifdef SHARED
/* When loading into a namespace other than the base one we must
avoid loading ld.so since there can only be one copy. Ever. */
- if (__builtin_expect (nsid != LM_ID_BASE, 0)
- && ((st.st_ino == GL(dl_rtld_map).l_ino
- && st.st_dev == GL(dl_rtld_map).l_dev)
+ if (__glibc_unlikely (nsid != LM_ID_BASE)
+ && (_dl_file_id_match_p (&id, &GL(dl_rtld_map).l_file_id)
|| _dl_name_match_p (name, &GL(dl_rtld_map))))
{
/* This is indeed ld.so. Create a new link_map which refers to
@@ -999,7 +943,7 @@ _dl_map_object_from_fd (const char *name, int fd, struct filebuf *fbp,
}
/* Print debugging message. */
- if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_FILES, 0))
+ if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES))
_dl_debug_printf ("file=%s [%lu]; generating link map\n", name, nsid);
/* This is the ELF header. We read it in `open_verify'. */
@@ -1026,7 +970,7 @@ _dl_map_object_from_fd (const char *name, int fd, struct filebuf *fbp,
#ifdef SHARED
/* Auditing checkpoint: we are going to add new objects. */
if ((mode & __RTLD_AUDIT) == 0
- && __builtin_expect (GLRO(dl_naudit) > 0, 0))
+ && __glibc_unlikely (GLRO(dl_naudit) > 0))
{
struct link_map *head = GL(dl_ns)[nsid]._ns_loaded;
/* Do not call the functions for any auditing object. */
@@ -1057,7 +1001,7 @@ _dl_map_object_from_fd (const char *name, int fd, struct filebuf *fbp,
/* Enter the new object in the list of loaded objects. */
l = _dl_new_object (realname, name, l_type, loader, mode, nsid);
- if (__builtin_expect (l == NULL, 0))
+ if (__glibc_unlikely (l == NULL))
{
#ifdef SHARED
fail_new:
@@ -1093,12 +1037,7 @@ _dl_map_object_from_fd (const char *name, int fd, struct filebuf *fbp,
{
/* Scan the program header table, collecting its load commands. */
- struct loadcmd
- {
- ElfW(Addr) mapstart, mapend, dataend, allocend;
- ElfW(Off) mapoff;
- int prot;
- } loadcmds[l->l_phnum], *c;
+ struct loadcmd loadcmds[l->l_phnum];
size_t nloadcmds = 0;
bool has_holes = false;
@@ -1124,21 +1063,20 @@ _dl_map_object_from_fd (const char *name, int fd, struct filebuf *fbp,
case PT_LOAD:
/* A load command tells us to map in part of the file.
We record the load commands and process them all later. */
- if (__builtin_expect ((ph->p_align & (GLRO(dl_pagesize) - 1)) != 0,
- 0))
+ if (__glibc_unlikely ((ph->p_align & (GLRO(dl_pagesize) - 1)) != 0))
{
errstring = N_("ELF load command alignment not page-aligned");
goto call_lose;
}
- if (__builtin_expect (((ph->p_vaddr - ph->p_offset)
- & (ph->p_align - 1)) != 0, 0))
+ if (__glibc_unlikely (((ph->p_vaddr - ph->p_offset)
+ & (ph->p_align - 1)) != 0))
{
errstring
= N_("ELF load command address/offset not properly aligned");
goto call_lose;
}
- c = &loadcmds[nloadcmds++];
+ struct loadcmd *c = &loadcmds[nloadcmds++];
c->mapstart = ph->p_vaddr & ~(GLRO(dl_pagesize) - 1);
c->mapend = ((ph->p_vaddr + ph->p_filesz + GLRO(dl_pagesize) - 1)
& ~(GLRO(dl_pagesize) - 1));
@@ -1184,10 +1122,10 @@ _dl_map_object_from_fd (const char *name, int fd, struct filebuf *fbp,
/* If not loading the initial set of shared libraries,
check whether we should permit loading a TLS segment. */
- if (__builtin_expect (l->l_type == lt_library, 1)
+ if (__glibc_likely (l->l_type == lt_library)
/* If GL(dl_tls_dtv_slotinfo_list) == NULL, then rtld.c did
not set up TLS data structures, so don't use them now. */
- || __builtin_expect (GL(dl_tls_dtv_slotinfo_list) != NULL, 1))
+ || __glibc_likely (GL(dl_tls_dtv_slotinfo_list) != NULL))
{
/* Assign the next available module ID. */
l->l_tls_modid = _dl_next_tls_modid ();
@@ -1214,9 +1152,8 @@ _dl_map_object_from_fd (const char *name, int fd, struct filebuf *fbp,
/* The first call allocates TLS bookkeeping data structures.
Then we allocate the TCB for the initial thread. */
- if (__builtin_expect (_dl_tls_setup (), 0)
- || __builtin_expect ((tcb = _dl_allocate_tls (NULL)) == NULL,
- 0))
+ if (__glibc_unlikely (_dl_tls_setup ())
+ || __glibc_unlikely ((tcb = _dl_allocate_tls (NULL)) == NULL))
{
errval = ENOMEM;
errstring = N_("\
@@ -1225,8 +1162,8 @@ cannot allocate TLS data structures for initial thread");
}
/* Now we install the TCB in the thread register. */
- errstring = TLS_INIT_TP (tcb, 0);
- if (__builtin_expect (errstring == NULL, 1))
+ errstring = TLS_INIT_TP (tcb);
+ if (__glibc_likely (errstring == NULL))
{
/* Now we are all good. */
l->l_tls_modid = ++GL(dl_tls_max_dtv_idx);
@@ -1256,7 +1193,7 @@ cannot allocate TLS data structures for initial thread");
break;
}
- if (__builtin_expect (nloadcmds == 0, 0))
+ if (__glibc_unlikely (nloadcmds == 0))
{
/* This only happens for a bogus object that will be caught with
another error below. But we don't want to go through the
@@ -1265,159 +1202,31 @@ cannot allocate TLS data structures for initial thread");
goto call_lose;
}
- /* Now process the load commands and map segments into memory. */
- c = loadcmds;
-
- /* Length of the sections to be loaded. */
- maplength = loadcmds[nloadcmds - 1].allocend - c->mapstart;
-
- if (__builtin_expect (type, ET_DYN) == ET_DYN)
- {
- /* This is a position-independent shared object. We can let the
- kernel map it anywhere it likes, but we must have space for all
- the segments in their specified positions relative to the first.
- So we map the first segment without MAP_FIXED, but with its
- extent increased to cover all the segments. Then we remove
- access from excess portion, and there is known sufficient space
- there to remap from the later segments.
-
- As a refinement, sometimes we have an address that we would
- prefer to map such objects at; but this is only a preference,
- the OS can do whatever it likes. */
- ElfW(Addr) mappref;
- mappref = (ELF_PREFERRED_ADDRESS (loader, maplength,
- c->mapstart & GLRO(dl_use_load_bias))
- - MAP_BASE_ADDR (l));
-
- /* Remember which part of the address space this object uses. */
- l->l_map_start = (ElfW(Addr)) __mmap ((void *) mappref, maplength,
- c->prot,
- MAP_COPY|MAP_FILE,
- fd, c->mapoff);
- if (__builtin_expect ((void *) l->l_map_start == MAP_FAILED, 0))
- {
- map_error:
- errstring = N_("failed to map segment from shared object");
- goto call_lose_errno;
- }
-
- l->l_map_end = l->l_map_start + maplength;
- l->l_addr = l->l_map_start - c->mapstart;
-
- if (has_holes)
- /* Change protection on the excess portion to disallow all access;
- the portions we do not remap later will be inaccessible as if
- unallocated. Then jump into the normal segment-mapping loop to
- handle the portion of the segment past the end of the file
- mapping. */
- __mprotect ((caddr_t) (l->l_addr + c->mapend),
- loadcmds[nloadcmds - 1].mapstart - c->mapend,
- PROT_NONE);
-
- l->l_contiguous = 1;
-
- goto postmap;
- }
-
- /* This object is loaded at a fixed address. This must never
- happen for objects loaded with dlopen(). */
- if (__builtin_expect ((mode & __RTLD_OPENEXEC) == 0, 0))
+ if (__glibc_unlikely (type != ET_DYN)
+ && __glibc_unlikely ((mode & __RTLD_OPENEXEC) == 0))
{
+ /* This object is loaded at a fixed address. This must never
+ happen for objects loaded with dlopen. */
errstring = N_("cannot dynamically load executable");
goto call_lose;
}
- /* Notify ELF_PREFERRED_ADDRESS that we have to load this one
- fixed. */
- ELF_FIXED_ADDRESS (loader, c->mapstart);
-
-
- /* Remember which part of the address space this object uses. */
- l->l_map_start = c->mapstart + l->l_addr;
- l->l_map_end = l->l_map_start + maplength;
- l->l_contiguous = !has_holes;
-
- while (c < &loadcmds[nloadcmds])
- {
- if (c->mapend > c->mapstart
- /* Map the segment contents from the file. */
- && (__mmap ((void *) (l->l_addr + c->mapstart),
- c->mapend - c->mapstart, c->prot,
- MAP_FIXED|MAP_COPY|MAP_FILE,
- fd, c->mapoff)
- == MAP_FAILED))
- goto map_error;
-
- postmap:
- if (c->prot & PROT_EXEC)
- l->l_text_end = l->l_addr + c->mapend;
-
- if (l->l_phdr == 0
- && c->mapoff <= header->e_phoff
- && ((size_t) (c->mapend - c->mapstart + c->mapoff)
- >= header->e_phoff + header->e_phnum * sizeof (ElfW(Phdr))))
- /* Found the program header in this segment. */
- l->l_phdr = (void *) (uintptr_t) (c->mapstart + header->e_phoff
- - c->mapoff);
-
- if (c->allocend > c->dataend)
- {
- /* Extra zero pages should appear at the end of this segment,
- after the data mapped from the file. */
- ElfW(Addr) zero, zeroend, zeropage;
-
- zero = l->l_addr + c->dataend;
- zeroend = l->l_addr + c->allocend;
- zeropage = ((zero + GLRO(dl_pagesize) - 1)
- & ~(GLRO(dl_pagesize) - 1));
-
- if (zeroend < zeropage)
- /* All the extra data is in the last page of the segment.
- We can just zero it. */
- zeropage = zeroend;
-
- if (zeropage > zero)
- {
- /* Zero the final part of the last page of the segment. */
- if (__builtin_expect ((c->prot & PROT_WRITE) == 0, 0))
- {
- /* Dag nab it. */
- if (__mprotect ((caddr_t) (zero
- & ~(GLRO(dl_pagesize) - 1)),
- GLRO(dl_pagesize), c->prot|PROT_WRITE) < 0)
- {
- errstring = N_("cannot change memory protections");
- goto call_lose_errno;
- }
- }
- memset ((void *) zero, '\0', zeropage - zero);
- if (__builtin_expect ((c->prot & PROT_WRITE) == 0, 0))
- __mprotect ((caddr_t) (zero & ~(GLRO(dl_pagesize) - 1)),
- GLRO(dl_pagesize), c->prot);
- }
-
- if (zeroend > zeropage)
- {
- /* Map the remaining zero pages in from the zero fill FD. */
- caddr_t mapat;
- mapat = __mmap ((caddr_t) zeropage, zeroend - zeropage,
- c->prot, MAP_ANON|MAP_PRIVATE|MAP_FIXED,
- -1, 0);
- if (__builtin_expect (mapat == MAP_FAILED, 0))
- {
- errstring = N_("cannot map zero-fill pages");
- goto call_lose_errno;
- }
- }
- }
-
- ++c;
- }
+ /* Length of the sections to be loaded. */
+ maplength = loadcmds[nloadcmds - 1].allocend - loadcmds[0].mapstart;
+
+ /* Now process the load commands and map segments into memory.
+ This is responsible for filling in:
+ l_map_start, l_map_end, l_addr, l_contiguous, l_text_end, l_phdr
+ */
+ errstring = _dl_map_segments (l, fd, header, type, loadcmds, nloadcmds,
+ maplength, has_holes, loader);
+ if (__glibc_unlikely (errstring != NULL))
+ goto call_lose;
}
if (l->l_ld == 0)
{
- if (__builtin_expect (type == ET_DYN, 0))
+ if (__glibc_unlikely (type == ET_DYN))
{
errstring = N_("object file has no dynamic section");
goto call_lose;
@@ -1430,11 +1239,11 @@ cannot allocate TLS data structures for initial thread");
/* Make sure we are not dlopen'ing an object that has the
DF_1_NOOPEN flag set. */
- if (__builtin_expect (l->l_flags_1 & DF_1_NOOPEN, 0)
+ if (__glibc_unlikely (l->l_flags_1 & DF_1_NOOPEN)
&& (mode & __RTLD_DLOPEN))
{
/* We are not supposed to load this object. Free all resources. */
- __munmap ((void *) l->l_map_start, l->l_map_end - l->l_map_start);
+ _dl_unmap_segments (l);
if (!l->l_libname->dont_free)
free (l->l_libname);
@@ -1467,10 +1276,9 @@ cannot allocate TLS data structures for initial thread");
/* Adjust the PT_PHDR value by the runtime load address. */
l->l_phdr = (ElfW(Phdr) *) ((ElfW(Addr)) l->l_phdr + l->l_addr);
- if (__builtin_expect ((stack_flags &~ GL(dl_stack_flags)) & PF_X, 0))
+ if (__glibc_unlikely ((stack_flags &~ GL(dl_stack_flags)) & PF_X))
{
- if (__builtin_expect (__check_caller (RETURN_ADDRESS (0), allow_ldso),
- 0) != 0)
+ if (__glibc_unlikely (__check_caller (RETURN_ADDRESS (0), allow_ldso) != 0))
{
errstring = N_("invalid caller");
goto call_lose;
@@ -1490,7 +1298,7 @@ cannot allocate TLS data structures for initial thread");
const uintptr_t relro_end = ((m->l_addr + m->l_relro_addr
+ m->l_relro_size)
& -GLRO(dl_pagesize));
- if (__builtin_expect (p + s <= relro_end, 1))
+ if (__glibc_likely (p + s <= relro_end))
{
/* The variable lies in the region protected by RELRO. */
if (__mprotect ((void *) p, s, PROT_READ|PROT_WRITE) < 0)
@@ -1526,7 +1334,7 @@ cannot enable executable stack as shared object requires");
l->l_tls_initimage = (char *) l->l_tls_initimage + l->l_addr;
/* We are done mapping in the file. We no longer need the descriptor. */
- if (__builtin_expect (__close (fd) != 0, 0))
+ if (__glibc_unlikely (__close (fd) != 0))
{
errstring = N_("cannot close file descriptor");
goto call_lose_errno;
@@ -1534,12 +1342,12 @@ cannot enable executable stack as shared object requires");
/* Signal that we closed the file. */
fd = -1;
- if (l->l_type == lt_library && type == ET_EXEC)
- l->l_type = lt_executable;
+ /* If this is ET_EXEC, we should have loaded it as lt_executable. */
+ assert (type != ET_EXEC || l->l_type == lt_executable);
l->l_entry += l->l_addr;
- if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_FILES, 0))
+ if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES))
_dl_debug_printf ("\
dynamic: 0x%0*lx base: 0x%0*lx size: 0x%0*Zx\n\
entry: 0x%0*lx phdr: 0x%0*lx phnum: %*u\n\n",
@@ -1560,7 +1368,7 @@ cannot enable executable stack as shared object requires");
/* If this object has DT_SYMBOLIC set modify now its scope. We don't
have to do this for the main map. */
if ((mode & RTLD_DEEPBIND) == 0
- && __builtin_expect (l->l_info[DT_SYMBOLIC] != NULL, 0)
+ && __glibc_unlikely (l->l_info[DT_SYMBOLIC] != NULL)
&& &l->l_searchlist != l->l_scope[0])
{
/* Create an appropriate searchlist. It contains only this map.
@@ -1581,12 +1389,11 @@ cannot enable executable stack as shared object requires");
GL(dl_initfirst) = l;
/* Finally the file information. */
- l->l_dev = st.st_dev;
- l->l_ino = st.st_ino;
+ l->l_file_id = id;
/* When we profile the SONAME might be needed for something else but
loading. Add it right away. */
- if (__builtin_expect (GLRO(dl_profile) != NULL, 0)
+ if (__glibc_unlikely (GLRO(dl_profile) != NULL)
&& l->l_info[DT_SONAME] != NULL)
add_name_to_object (l, ((const char *) D_PTR (l, l_info[DT_STRTAB])
+ l->l_info[DT_SONAME]->d_un.d_val));
@@ -1600,7 +1407,7 @@ cannot enable executable stack as shared object requires");
#ifdef SHARED
/* Auditing checkpoint: we have a new object. */
- if (__builtin_expect (GLRO(dl_naudit) > 0, 0)
+ if (__glibc_unlikely (GLRO(dl_naudit) > 0)
&& !GL(dl_ns)[l->l_ns]._ns_loaded->l_auditing)
{
struct audit_ifaces *afct = GLRO(dl_audit);
@@ -1667,7 +1474,7 @@ print_search_path (struct r_search_path_elem **list,
user might want to know about this. */
static int
open_verify (const char *name, struct filebuf *fbp, struct link_map *loader,
- int whatcode, bool *found_other_class, bool free_name)
+ int whatcode, int mode, bool *found_other_class, bool free_name)
{
/* This is the expected ELF header. */
#define ELF32_CLASS ELFCLASS32
@@ -1704,7 +1511,7 @@ open_verify (const char *name, struct filebuf *fbp, struct link_map *loader,
#ifdef SHARED
/* Give the auditing libraries a chance. */
- if (__builtin_expect (GLRO(dl_naudit) > 0, 0) && whatcode != 0
+ if (__glibc_unlikely (GLRO(dl_naudit) > 0) && whatcode != 0
&& loader->l_auditing == 0)
{
struct audit_ifaces *afct = GLRO(dl_audit);
@@ -1741,20 +1548,20 @@ open_verify (const char *name, struct filebuf *fbp, struct link_map *loader,
assert (sizeof (fbp->buf) > sizeof (ElfW(Ehdr)));
/* Read in the header. */
do
- {
- ssize_t retlen = __libc_read (fd, fbp->buf + fbp->len,
+ {
+ ssize_t retlen = __libc_read (fd, fbp->buf + fbp->len,
sizeof (fbp->buf) - fbp->len);
if (retlen <= 0)
break;
fbp->len += retlen;
}
- while (__builtin_expect (fbp->len < sizeof (ElfW(Ehdr)), 0));
+ while (__glibc_unlikely (fbp->len < sizeof (ElfW(Ehdr))));
/* This is where the ELF header is loaded. */
ehdr = (ElfW(Ehdr) *) fbp->buf;
/* Now run the tests. */
- if (__builtin_expect (fbp->len < (ssize_t) sizeof (ElfW(Ehdr)), 0))
+ if (__glibc_unlikely (fbp->len < (ssize_t) sizeof (ElfW(Ehdr))))
{
errval = errno;
errstring = (errval == 0
@@ -1770,14 +1577,13 @@ open_verify (const char *name, struct filebuf *fbp, struct link_map *loader,
}
/* See whether the ELF header is what we expect. */
- if (__builtin_expect (! VALID_ELF_HEADER (ehdr->e_ident, expected,
+ if (__glibc_unlikely (! VALID_ELF_HEADER (ehdr->e_ident, expected,
EI_ABIVERSION)
|| !VALID_ELF_ABIVERSION (ehdr->e_ident[EI_OSABI],
ehdr->e_ident[EI_ABIVERSION])
|| memcmp (&ehdr->e_ident[EI_PAD],
&expected[EI_PAD],
- EI_NIDENT - EI_PAD) != 0,
- 0))
+ EI_NIDENT - EI_PAD) != 0))
{
/* Something is wrong. */
const Elf32_Word *magp = (const void *) ehdr->e_ident;
@@ -1830,21 +1636,31 @@ open_verify (const char *name, struct filebuf *fbp, struct link_map *loader,
goto call_lose;
}
- if (__builtin_expect (ehdr->e_version, EV_CURRENT) != EV_CURRENT)
+ if (__glibc_unlikely (ehdr->e_version != EV_CURRENT))
{
errstring = N_("ELF file version does not match current one");
goto call_lose;
}
- if (! __builtin_expect (elf_machine_matches_host (ehdr), 1))
+ if (! __glibc_likely (elf_machine_matches_host (ehdr)))
goto close_and_out;
- else if (__builtin_expect (ehdr->e_type, ET_DYN) != ET_DYN
- && __builtin_expect (ehdr->e_type, ET_EXEC) != ET_EXEC)
+ else if (__glibc_unlikely (ehdr->e_type != ET_DYN
+ && ehdr->e_type != ET_EXEC))
{
errstring = N_("only ET_DYN and ET_EXEC can be loaded");
goto call_lose;
}
- else if (__builtin_expect (ehdr->e_phentsize, sizeof (ElfW(Phdr)))
- != sizeof (ElfW(Phdr)))
+ else if (__glibc_unlikely (ehdr->e_type == ET_EXEC
+ && (mode & __RTLD_OPENEXEC) == 0))
+ {
+ /* BZ #16634. It is an error to dlopen ET_EXEC (unless
+ __RTLD_OPENEXEC is explicitly set). We return error here
+ so that code in _dl_map_object_from_fd does not try to set
+ l_tls_modid for this module. */
+
+ errstring = N_("cannot dynamically load executable");
+ goto call_lose;
+ }
+ else if (__glibc_unlikely (ehdr->e_phentsize != sizeof (ElfW(Phdr))))
{
errstring = N_("ELF file's phentsize not the expected size");
goto call_lose;
@@ -1866,6 +1682,11 @@ open_verify (const char *name, struct filebuf *fbp, struct link_map *loader,
}
}
+ if (__glibc_unlikely (elf_machine_reject_phdr_p
+ (phdr, ehdr->e_phnum, fbp->buf, fbp->len,
+ loader, fd)))
+ goto close_and_out;
+
/* Check .note.ABI-tag if present. */
for (ph = phdr; ph < &phdr[ehdr->e_phnum]; ++ph)
if (ph->p_type == PT_NOTE && ph->p_filesz >= 32 && ph->p_align >= 4)
@@ -1928,7 +1749,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, int mode,
struct r_search_path_struct *sps, char **realname,
struct filebuf *fbp, struct link_map *loader, int whatcode,
bool *found_other_class)
@@ -1939,7 +1760,7 @@ open_path (const char *name, size_t namelen, int secure,
const char *current_what = NULL;
int any = 0;
- if (__builtin_expect (dirs == NULL, 0))
+ if (__glibc_unlikely (dirs == NULL))
/* We're called before _dl_init_paths when loading the main executable
given on the command line when rtld is run directly. */
return -1;
@@ -1956,7 +1777,7 @@ open_path (const char *name, size_t namelen, int secure,
/* If we are debugging the search for libraries print the path
now if it hasn't happened now. */
- if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_LIBS, 0)
+ if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_LIBS)
&& current_what != this_dir->what)
{
current_what = this_dir->what;
@@ -1977,11 +1798,11 @@ open_path (const char *name, size_t namelen, int secure,
- buf);
/* Print name we try if this is wanted. */
- if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_LIBS, 0))
+ if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_LIBS))
_dl_debug_printf (" trying file=%s\n", buf);
- fd = open_verify (buf, fbp, loader, whatcode, found_other_class,
- false);
+ fd = open_verify (buf, fbp, loader, whatcode, mode,
+ found_other_class, false);
if (this_dir->status[cnt] == unknown)
{
if (fd != -1)
@@ -2010,8 +1831,8 @@ open_path (const char *name, size_t namelen, int secure,
/* Remember whether we found any existing directory. */
here_any |= this_dir->status[cnt] != nonexisting;
- if (fd != -1 && __builtin_expect (secure, 0)
- && INTUSE(__libc_enable_secure))
+ if (fd != -1 && __glibc_unlikely (mode & __RTLD_SECURE)
+ && __libc_enable_secure)
{
/* This is an extra security effort to make sure nobody can
preload broken shared objects which are in the trusted
@@ -2059,16 +1880,16 @@ open_path (const char *name, size_t namelen, int secure,
while (*++dirs != NULL);
/* Remove the whole path if none of the directories exists. */
- if (__builtin_expect (! any, 0))
+ if (__glibc_unlikely (! any))
{
/* Paths which were allocated using the minimal malloc() in ld.so
must not be freed using the general free() in libc. */
if (sps->malloced)
free (sps->dirs);
- /* rtld_search_dirs is attribute_relro, therefore avoid writing
- into it. */
- if (sps != &rtld_search_dirs)
+ /* rtld_search_dirs and env_path_list are attribute_relro, therefore
+ avoid writing into it. */
+ if (sps != &rtld_search_dirs && sps != &env_path_list)
sps->dirs = (void *) -1;
}
@@ -2097,14 +1918,13 @@ _dl_map_object (struct link_map *loader, const char *name,
/* 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)
+ if (__glibc_unlikely ((l->l_faked | l->l_removed) != 0))
continue;
if (!_dl_name_match_p (name, l))
{
const char *soname;
- if (__builtin_expect (l->l_soname_added, 1)
+ if (__glibc_likely (l->l_soname_added)
|| l->l_info[DT_SONAME] == NULL)
continue;
@@ -2123,7 +1943,7 @@ _dl_map_object (struct link_map *loader, const char *name,
}
/* Display information if we are debugging. */
- if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_FILES, 0)
+ if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES)
&& loader != NULL)
_dl_debug_printf ((mode & __RTLD_CALLMAP) == 0
? "\nfile=%s [%lu]; needed by %s [%lu]\n"
@@ -2133,7 +1953,7 @@ _dl_map_object (struct link_map *loader, const char *name,
#ifdef SHARED
/* Give the auditing libraries a chance to change the name before we
try anything. */
- if (__builtin_expect (GLRO(dl_naudit) > 0, 0)
+ if (__glibc_unlikely (GLRO(dl_naudit) > 0)
&& (loader == NULL || loader->l_auditing == 0))
{
struct audit_ifaces *afct = GLRO(dl_audit);
@@ -2165,7 +1985,7 @@ _dl_map_object (struct link_map *loader, const char *name,
size_t namelen = strlen (name) + 1;
- if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_LIBS, 0))
+ if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_LIBS))
_dl_debug_printf ("find library=%s [%lu]; searching\n", name, nsid);
fd = -1;
@@ -2184,7 +2004,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, mode,
&l->l_rpath_dirs,
&realname, &fb, loader, LA_SER_RUNPATH,
&found_other_class);
@@ -2200,7 +2020,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, mode,
&main_map->l_rpath_dirs,
&realname, &fb, loader ?: main_map, LA_SER_RUNPATH,
&found_other_class);
@@ -2208,7 +2028,7 @@ _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, mode, &env_path_list,
&realname, &fb,
loader ?: GL(dl_ns)[LM_ID_BASE]._ns_loaded,
LA_SER_LIBPATH, &found_other_class);
@@ -2217,19 +2037,19 @@ _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, mode,
&loader->l_runpath_dirs, &realname, &fb, loader,
LA_SER_RUNPATH, &found_other_class);
#ifdef USE_LDCONFIG
if (fd == -1
- && (__builtin_expect (! (mode & __RTLD_SECURE), 1)
- || ! INTUSE(__libc_enable_secure))
- && __builtin_expect (GLRO(dl_inhibit_cache) == 0, 1))
+ && (__glibc_likely ((mode & __RTLD_SECURE) == 0)
+ || ! __libc_enable_secure)
+ && __glibc_likely (GLRO(dl_inhibit_cache) == 0))
{
/* 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);
+ char *cached = _dl_load_cache_lookup (name);
if (cached != NULL)
{
@@ -2243,7 +2063,7 @@ _dl_map_object (struct link_map *loader, const char *name,
/* If the loader has the DF_1_NODEFLIB flag set we must not
use a cache entry from any of these directories. */
- if (__builtin_expect (l->l_flags_1 & DF_1_NODEFLIB, 0))
+ if (__glibc_unlikely (l->l_flags_1 & DF_1_NODEFLIB))
{
const char *dirp = system_dirs;
unsigned int cnt = 0;
@@ -2253,6 +2073,7 @@ _dl_map_object (struct link_map *loader, const char *name,
if (memcmp (cached, dirp, system_dirs_len[cnt]) == 0)
{
/* The prefix matches. Don't use the entry. */
+ free (cached);
cached = NULL;
break;
}
@@ -2267,16 +2088,12 @@ _dl_map_object (struct link_map *loader, const char *name,
{
fd = open_verify (cached,
&fb, loader ?: GL(dl_ns)[nsid]._ns_loaded,
- LA_SER_CONFIG, &found_other_class, false);
- if (__builtin_expect (fd != -1, 1))
- {
- realname = local_strdup (cached);
- if (realname == NULL)
- {
- __close (fd);
- fd = -1;
- }
- }
+ LA_SER_CONFIG, mode, &found_other_class,
+ false);
+ if (__glibc_likely (fd != -1))
+ realname = cached;
+ else
+ free (cached);
}
}
}
@@ -2285,13 +2102,13 @@ _dl_map_object (struct link_map *loader, const char *name,
/* Finally, try the default path. */
if (fd == -1
&& ((l = loader ?: GL(dl_ns)[nsid]._ns_loaded) == NULL
- || __builtin_expect (!(l->l_flags_1 & DF_1_NODEFLIB), 1))
+ || __glibc_likely (!(l->l_flags_1 & DF_1_NODEFLIB)))
&& rtld_search_dirs.dirs != (void *) -1)
- fd = open_path (name, namelen, mode & __RTLD_SECURE, &rtld_search_dirs,
+ fd = open_path (name, namelen, mode, &rtld_search_dirs,
&realname, &fb, l, LA_SER_DEFAULT, &found_other_class);
/* Add another newline when we are tracing the library loading. */
- if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_LIBS, 0))
+ if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_LIBS))
_dl_debug_printf ("\n");
}
else
@@ -2299,15 +2116,15 @@ _dl_map_object (struct link_map *loader, const char *name,
/* The path may contain dynamic string tokens. */
realname = (loader
? expand_dynamic_string_token (loader, name, 0)
- : local_strdup (name));
+ : __strdup (name));
if (realname == NULL)
fd = -1;
else
{
fd = open_verify (realname, &fb,
- loader ?: GL(dl_ns)[nsid]._ns_loaded, 0,
+ loader ?: GL(dl_ns)[nsid]._ns_loaded, 0, mode,
&found_other_class, true);
- if (__builtin_expect (fd, 0) == -1)
+ if (__glibc_unlikely (fd == -1))
free (realname);
}
}
@@ -2321,10 +2138,10 @@ _dl_map_object (struct link_map *loader, const char *name,
if (mode & __RTLD_CALLMAP)
loader = NULL;
- if (__builtin_expect (fd, 0) == -1)
+ if (__glibc_unlikely (fd == -1))
{
if (trace_mode
- && __builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_PRELINK, 0) == 0)
+ && __glibc_likely ((GLRO(dl_debug_mask) & DL_DEBUG_PRELINK) == 0))
{
/* We haven't found an appropriate library. But since we
are only interested in the list of libraries this isn't
@@ -2333,7 +2150,7 @@ _dl_map_object (struct link_map *loader, const char *name,
static const Elf_Symndx dummy_bucket = STN_UNDEF;
/* Allocate a new object map. */
- if ((name_copy = local_strdup (name)) == NULL
+ if ((name_copy = __strdup (name)) == NULL
|| (l = _dl_new_object (name_copy, name, type, loader,
mode, nsid)) == NULL)
{
@@ -2370,6 +2187,45 @@ _dl_map_object (struct link_map *loader, const char *name,
&stack_end, nsid);
}
+struct add_path_state
+{
+ bool counting;
+ unsigned int idx;
+ Dl_serinfo *si;
+ char *allocptr;
+};
+
+static void
+add_path (struct add_path_state *p, const struct r_search_path_struct *sps,
+ unsigned int flags)
+{
+ if (sps->dirs != (void *) -1)
+ {
+ struct r_search_path_elem **dirs = sps->dirs;
+ do
+ {
+ const struct r_search_path_elem *const r = *dirs++;
+ if (p->counting)
+ {
+ p->si->dls_cnt++;
+ p->si->dls_size += MAX (2, r->dirnamelen);
+ }
+ else
+ {
+ Dl_serpath *const sp = &p->si->dls_serpath[p->idx++];
+ sp->dls_name = p->allocptr;
+ if (r->dirnamelen < 2)
+ *p->allocptr++ = r->dirnamelen ? '/' : '.';
+ else
+ p->allocptr = __mempcpy (p->allocptr,
+ r->dirname, r->dirnamelen - 1);
+ *p->allocptr++ = '\0';
+ sp->dls_flags = flags;
+ }
+ }
+ while (*dirs != NULL);
+ }
+}
void
internal_function
@@ -2381,38 +2237,15 @@ _dl_rtld_di_serinfo (struct link_map *loader, Dl_serinfo *si, bool counting)
si->dls_size = 0;
}
- unsigned int idx = 0;
- char *allocptr = (char *) &si->dls_serpath[si->dls_cnt];
- void add_path (const struct r_search_path_struct *sps, unsigned int flags)
-# define add_path(sps, flags) add_path(sps, 0) /* XXX */
+ struct add_path_state p =
{
- if (sps->dirs != (void *) -1)
- {
- struct r_search_path_elem **dirs = sps->dirs;
- do
- {
- const struct r_search_path_elem *const r = *dirs++;
- if (counting)
- {
- si->dls_cnt++;
- si->dls_size += MAX (2, r->dirnamelen);
- }
- else
- {
- Dl_serpath *const sp = &si->dls_serpath[idx++];
- sp->dls_name = allocptr;
- if (r->dirnamelen < 2)
- *allocptr++ = r->dirnamelen ? '/' : '.';
- else
- allocptr = __mempcpy (allocptr,
- r->dirname, r->dirnamelen - 1);
- *allocptr++ = '\0';
- sp->dls_flags = flags;
- }
- }
- while (*dirs != NULL);
- }
- }
+ .counting = counting,
+ .idx = 0,
+ .si = si,
+ .allocptr = (char *) &si->dls_serpath[si->dls_cnt]
+ };
+
+# define add_path(p, sps, flags) add_path(p, sps, 0) /* XXX */
/* When the object has the RUNPATH information we don't use any RPATHs. */
if (loader->l_info[DT_RUNPATH] == NULL)
@@ -2424,7 +2257,7 @@ _dl_rtld_di_serinfo (struct link_map *loader, Dl_serinfo *si, bool counting)
do
{
if (cache_rpath (l, &l->l_rpath_dirs, DT_RPATH, "RPATH"))
- add_path (&l->l_rpath_dirs, XXX_RPATH);
+ add_path (&p, &l->l_rpath_dirs, XXX_RPATH);
l = l->l_loader;
}
while (l != NULL);
@@ -2435,16 +2268,16 @@ _dl_rtld_di_serinfo (struct link_map *loader, Dl_serinfo *si, bool counting)
l = GL(dl_ns)[LM_ID_BASE]._ns_loaded;
if (l != NULL && l->l_type != lt_loaded && l != loader)
if (cache_rpath (l, &l->l_rpath_dirs, DT_RPATH, "RPATH"))
- add_path (&l->l_rpath_dirs, XXX_RPATH);
+ add_path (&p, &l->l_rpath_dirs, XXX_RPATH);
}
}
/* Try the LD_LIBRARY_PATH environment variable. */
- add_path (&env_path_list, XXX_ENV);
+ add_path (&p, &env_path_list, XXX_ENV);
/* Look at the RUNPATH information for this binary. */
if (cache_rpath (loader, &loader->l_runpath_dirs, DT_RUNPATH, "RUNPATH"))
- add_path (&loader->l_runpath_dirs, XXX_RUNPATH);
+ add_path (&p, &loader->l_runpath_dirs, XXX_RUNPATH);
/* XXX
Here is where ld.so.cache gets checked, but we don't have
@@ -2452,7 +2285,7 @@ _dl_rtld_di_serinfo (struct link_map *loader, Dl_serinfo *si, bool counting)
/* Finally, try the default path. */
if (!(loader->l_flags_1 & DF_1_NODEFLIB))
- add_path (&rtld_search_dirs, XXX_default);
+ add_path (&p, &rtld_search_dirs, XXX_default);
if (counting)
/* Count the struct size before the string area, which we didn't
diff --git a/elf/dl-load.h b/elf/dl-load.h
new file mode 100644
index 0000000000..1aa638ce6d
--- /dev/null
+++ b/elf/dl-load.h
@@ -0,0 +1,135 @@
+/* Map in a shared object's segments from the file.
+ Copyright (C) 1995-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/>. */
+
+#ifndef _DL_LOAD_H
+#define _DL_LOAD_H 1
+
+#include <link.h>
+#include <sys/mman.h>
+
+
+/* On some systems, no flag bits are given to specify file mapping. */
+#ifndef MAP_FILE
+# define MAP_FILE 0
+#endif
+
+/* The right way to map in the shared library files is MAP_COPY, which
+ makes a virtual copy of the data at the time of the mmap call; this
+ guarantees the mapped pages will be consistent even if the file is
+ overwritten. Some losing VM systems like Linux's lack MAP_COPY. All we
+ get is MAP_PRIVATE, which copies each page when it is modified; this
+ means if the file is overwritten, we may at some point get some pages
+ from the new version after starting with pages from the old version.
+
+ To make up for the lack and avoid the overwriting problem,
+ what Linux does have is MAP_DENYWRITE. This prevents anyone
+ from modifying the file while we have it mapped. */
+#ifndef MAP_COPY
+# ifdef MAP_DENYWRITE
+# define MAP_COPY (MAP_PRIVATE | MAP_DENYWRITE)
+# else
+# define MAP_COPY MAP_PRIVATE
+# endif
+#endif
+
+/* Some systems link their relocatable objects for another base address
+ than 0. We want to know the base address for these such that we can
+ subtract this address from the segment addresses during mapping.
+ This results in a more efficient address space usage. Defaults to
+ zero for almost all systems. */
+#ifndef MAP_BASE_ADDR
+# define MAP_BASE_ADDR(l) 0
+#endif
+
+
+/* Handle situations where we have a preferred location in memory for
+ the shared objects. */
+#ifdef ELF_PREFERRED_ADDRESS_DATA
+ELF_PREFERRED_ADDRESS_DATA;
+#endif
+#ifndef ELF_PREFERRED_ADDRESS
+# define ELF_PREFERRED_ADDRESS(loader, maplength, mapstartpref) (mapstartpref)
+#endif
+#ifndef ELF_FIXED_ADDRESS
+# define ELF_FIXED_ADDRESS(loader, mapstart) ((void) 0)
+#endif
+
+
+/* This structure describes one PT_LOAD command.
+ Its details have been expanded out and converted. */
+struct loadcmd
+{
+ ElfW(Addr) mapstart, mapend, dataend, allocend;
+ ElfW(Off) mapoff;
+ int prot; /* PROT_* bits. */
+};
+
+
+/* This is a subroutine of _dl_map_segments. It should be called for each
+ load command, some time after L->l_addr has been set correctly. It is
+ responsible for setting up the l_text_end and l_phdr fields. */
+static void __always_inline
+_dl_postprocess_loadcmd (struct link_map *l, const ElfW(Ehdr) *header,
+ const struct loadcmd *c)
+{
+ if (c->prot & PROT_EXEC)
+ l->l_text_end = l->l_addr + c->mapend;
+
+ if (l->l_phdr == 0
+ && c->mapoff <= header->e_phoff
+ && ((size_t) (c->mapend - c->mapstart + c->mapoff)
+ >= header->e_phoff + header->e_phnum * sizeof (ElfW(Phdr))))
+ /* Found the program header in this segment. */
+ l->l_phdr = (void *) (uintptr_t) (c->mapstart + header->e_phoff
+ - c->mapoff);
+}
+
+
+/* This is a subroutine of _dl_map_object_from_fd. It is responsible
+ for filling in several fields in *L: l_map_start, l_map_end, l_addr,
+ l_contiguous, l_text_end, l_phdr. On successful return, all the
+ segments are mapped (or copied, or whatever) from the file into their
+ final places in the address space, with the correct page permissions,
+ and any bss-like regions already zeroed. It returns a null pointer
+ on success, or an error message string (to be translated) on error
+ (having also set errno).
+
+ The file <dl-map-segments.h> defines this function. The canonical
+ implementation in elf/dl-map-segments.h might be replaced by a sysdeps
+ version. */
+static const char *_dl_map_segments (struct link_map *l, int fd,
+ const ElfW(Ehdr) *header, int type,
+ const struct loadcmd loadcmds[],
+ size_t nloadcmds,
+ const size_t maplength,
+ bool has_holes,
+ struct link_map *loader);
+
+/* All the error message strings _dl_map_segments might return are
+ listed here so that different implementations in different sysdeps
+ dl-map-segments.h files all use consistent strings that are
+ guaranteed to have translations. */
+#define DL_MAP_SEGMENTS_ERROR_MAP_SEGMENT \
+ N_("failed to map segment from shared object")
+#define DL_MAP_SEGMENTS_ERROR_MPROTECT \
+ N_("cannot change memory protections")
+#define DL_MAP_SEGMENTS_ERROR_MAP_ZERO_FILL \
+ N_("cannot map zero-fill pages")
+
+
+#endif /* dl-load.h */
diff --git a/elf/dl-lookup.c b/elf/dl-lookup.c
index a58e5bc72a..11cb44b451 100644
--- a/elf/dl-lookup.c
+++ b/elf/dl-lookup.c
@@ -1,5 +1,5 @@
/* Look up a symbol in the loaded objects.
- Copyright (C) 1995-2014 Free Software Foundation, Inc.
+ Copyright (C) 1995-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
@@ -31,10 +31,13 @@
#include <assert.h>
-#define VERSTAG(tag) (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGIDX (tag))
+/* Return nonzero if check_match should consider SYM to fail to match a
+ symbol reference for some machine-specific reason. */
+#ifndef ELF_MACHINE_SYM_NO_MATCH
+# define ELF_MACHINE_SYM_NO_MATCH(sym) 0
+#endif
-/* We need this string more than once. */
-static const char undefined_msg[] = "undefined symbol: ";
+#define VERSTAG(tag) (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGIDX (tag))
struct sym_val
@@ -68,6 +71,276 @@ struct sym_val
# define bump_num_relocations() ((void) 0)
#endif
+/* Utility function for do_lookup_x. The caller is called with undef_name,
+ ref, version, flags and type_class, and those are passed as the first
+ five arguments. The caller then computes sym, symidx, strtab, and map
+ and passes them as the next four arguments. Lastly the caller passes in
+ versioned_sym and num_versions which are modified by check_match during
+ the checking process. */
+static const ElfW(Sym) *
+check_match (const char *const undef_name,
+ const ElfW(Sym) *const ref,
+ const struct r_found_version *const version,
+ const int flags,
+ const int type_class,
+ const ElfW(Sym) *const sym,
+ const Elf_Symndx symidx,
+ const char *const strtab,
+ const struct link_map *const map,
+ const ElfW(Sym) **const versioned_sym,
+ int *const num_versions)
+{
+ unsigned int stt = ELFW(ST_TYPE) (sym->st_info);
+ assert (ELF_RTYPE_CLASS_PLT == 1);
+ if (__glibc_unlikely ((sym->st_value == 0 /* No value. */
+ && stt != STT_TLS)
+ || ELF_MACHINE_SYM_NO_MATCH (sym)
+ || (type_class & (sym->st_shndx == SHN_UNDEF))))
+ return NULL;
+
+ /* Ignore all but STT_NOTYPE, STT_OBJECT, STT_FUNC,
+ STT_COMMON, STT_TLS, and STT_GNU_IFUNC since these are no
+ code/data definitions. */
+#define ALLOWED_STT \
+ ((1 << STT_NOTYPE) | (1 << STT_OBJECT) | (1 << STT_FUNC) \
+ | (1 << STT_COMMON) | (1 << STT_TLS) | (1 << STT_GNU_IFUNC))
+ if (__glibc_unlikely (((1 << stt) & ALLOWED_STT) == 0))
+ return NULL;
+
+ if (sym != ref && strcmp (strtab + sym->st_name, undef_name))
+ /* Not the symbol we are looking for. */
+ return NULL;
+
+ const ElfW(Half) *verstab = map->l_versyms;
+ if (version != NULL)
+ {
+ if (__glibc_unlikely (verstab == NULL))
+ {
+ /* We need a versioned symbol but haven't found any. If
+ this is the object which is referenced in the verneed
+ entry it is a bug in the library since a symbol must
+ not simply disappear.
+
+ It would also be a bug in the object since it means that
+ the list of required versions is incomplete and so the
+ tests in dl-version.c haven't found a problem.*/
+ assert (version->filename == NULL
+ || ! _dl_name_match_p (version->filename, map));
+
+ /* Otherwise we accept the symbol. */
+ }
+ else
+ {
+ /* We can match the version information or use the
+ default one if it is not hidden. */
+ ElfW(Half) ndx = verstab[symidx] & 0x7fff;
+ if ((map->l_versions[ndx].hash != version->hash
+ || strcmp (map->l_versions[ndx].name, version->name))
+ && (version->hidden || map->l_versions[ndx].hash
+ || (verstab[symidx] & 0x8000)))
+ /* It's not the version we want. */
+ return NULL;
+ }
+ }
+ else
+ {
+ /* No specific version is selected. There are two ways we
+ can got here:
+
+ - a binary which does not include versioning information
+ is loaded
+
+ - dlsym() instead of dlvsym() is used to get a symbol which
+ might exist in more than one form
+
+ If the library does not provide symbol version information
+ there is no problem at all: we simply use the symbol if it
+ is defined.
+
+ These two lookups need to be handled differently if the
+ library defines versions. In the case of the old
+ unversioned application the oldest (default) version
+ should be used. In case of a dlsym() call the latest and
+ public interface should be returned. */
+ if (verstab != NULL)
+ {
+ if ((verstab[symidx] & 0x7fff)
+ >= ((flags & DL_LOOKUP_RETURN_NEWEST) ? 2 : 3))
+ {
+ /* Don't accept hidden symbols. */
+ if ((verstab[symidx] & 0x8000) == 0
+ && (*num_versions)++ == 0)
+ /* No version so far. */
+ *versioned_sym = sym;
+
+ return NULL;
+ }
+ }
+ }
+
+ /* There cannot be another entry for this symbol so stop here. */
+ return sym;
+}
+
+/* Utility function for do_lookup_unique. Add a symbol to TABLE. */
+static void
+enter_unique_sym (struct unique_sym *table, size_t size,
+ unsigned int hash, const char *name,
+ const ElfW(Sym) *sym, const struct link_map *map)
+{
+ size_t idx = hash % size;
+ size_t hash2 = 1 + hash % (size - 2);
+ while (table[idx].name != NULL)
+ {
+ idx += hash2;
+ if (idx >= size)
+ idx -= size;
+ }
+
+ table[idx].hashval = hash;
+ table[idx].name = name;
+ table[idx].sym = sym;
+ table[idx].map = map;
+}
+
+/* Utility function for do_lookup_x. Lookup an STB_GNU_UNIQUE symbol
+ in the unique symbol table, creating a new entry if necessary.
+ Return the matching symbol in RESULT. */
+static void
+do_lookup_unique (const char *undef_name, uint_fast32_t new_hash,
+ const struct link_map *map, struct sym_val *result,
+ int type_class, const ElfW(Sym) *sym, const char *strtab,
+ const ElfW(Sym) *ref, const struct link_map *undef_map)
+{
+ /* We have to determine whether we already found a symbol with this
+ name before. If not then we have to add it to the search table.
+ If we already found a definition we have to use it. */
+
+ struct unique_sym_table *tab
+ = &GL(dl_ns)[map->l_ns]._ns_unique_sym_table;
+
+ __rtld_lock_lock_recursive (tab->lock);
+
+ struct unique_sym *entries = tab->entries;
+ size_t size = tab->size;
+ if (entries != NULL)
+ {
+ size_t idx = new_hash % size;
+ size_t hash2 = 1 + new_hash % (size - 2);
+ while (1)
+ {
+ if (entries[idx].hashval == new_hash
+ && strcmp (entries[idx].name, undef_name) == 0)
+ {
+ if ((type_class & ELF_RTYPE_CLASS_COPY) != 0)
+ {
+ /* We possibly have to initialize the central
+ copy from the copy addressed through the
+ relocation. */
+ result->s = sym;
+ result->m = (struct link_map *) map;
+ }
+ else
+ {
+ result->s = entries[idx].sym;
+ result->m = (struct link_map *) entries[idx].map;
+ }
+ __rtld_lock_unlock_recursive (tab->lock);
+ return;
+ }
+
+ if (entries[idx].name == NULL)
+ break;
+
+ idx += hash2;
+ if (idx >= size)
+ idx -= size;
+ }
+
+ if (size * 3 <= tab->n_elements * 4)
+ {
+ /* Expand the table. */
+#ifdef RTLD_CHECK_FOREIGN_CALL
+ /* This must not happen during runtime relocations. */
+ assert (!RTLD_CHECK_FOREIGN_CALL);
+#endif
+ size_t newsize = _dl_higher_prime_number (size + 1);
+ struct unique_sym *newentries
+ = calloc (sizeof (struct unique_sym), newsize);
+ if (newentries == NULL)
+ {
+ nomem:
+ __rtld_lock_unlock_recursive (tab->lock);
+ _dl_fatal_printf ("out of memory\n");
+ }
+
+ for (idx = 0; idx < size; ++idx)
+ if (entries[idx].name != NULL)
+ enter_unique_sym (newentries, newsize, entries[idx].hashval,
+ entries[idx].name, entries[idx].sym,
+ entries[idx].map);
+
+ tab->free (entries);
+ tab->size = newsize;
+ size = newsize;
+ entries = tab->entries = newentries;
+ tab->free = free;
+ }
+ }
+ else
+ {
+#ifdef RTLD_CHECK_FOREIGN_CALL
+ /* This must not happen during runtime relocations. */
+ assert (!RTLD_CHECK_FOREIGN_CALL);
+#endif
+
+#ifdef SHARED
+ /* If tab->entries is NULL, but tab->size is not, it means
+ this is the second, conflict finding, lookup for
+ LD_TRACE_PRELINKING in _dl_debug_bindings. Don't
+ allocate anything and don't enter anything into the
+ hash table. */
+ if (__glibc_unlikely (tab->size))
+ {
+ assert (GLRO(dl_debug_mask) & DL_DEBUG_PRELINK);
+ goto success;
+ }
+#endif
+
+#define INITIAL_NUNIQUE_SYM_TABLE 31
+ size = INITIAL_NUNIQUE_SYM_TABLE;
+ entries = calloc (sizeof (struct unique_sym), size);
+ if (entries == NULL)
+ goto nomem;
+
+ tab->entries = entries;
+ tab->size = size;
+ tab->free = free;
+ }
+
+ if ((type_class & ELF_RTYPE_CLASS_COPY) != 0)
+ enter_unique_sym (entries, size, new_hash, strtab + sym->st_name, ref,
+ undef_map);
+ else
+ {
+ enter_unique_sym (entries, size,
+ new_hash, strtab + sym->st_name, sym, map);
+
+ if (map->l_type == lt_loaded)
+ /* Make sure we don't unload this object by
+ setting the appropriate flag. */
+ ((struct link_map *) map)->l_flags_1 |= DF_1_NODELETE;
+ }
+ ++tab->n_elements;
+
+#ifdef SHARED
+ success:
+#endif
+ __rtld_lock_unlock_recursive (tab->lock);
+
+ result->s = sym;
+ result->m = (struct link_map *) map;
+}
/* 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
@@ -90,11 +363,6 @@ do_lookup_x (const char *undef_name, uint_fast32_t new_hash,
do
{
- /* These variables are used in the nested function. */
- Elf_Symndx symidx;
- int num_versions = 0;
- const ElfW(Sym) *versioned_sym = NULL;
-
const struct link_map *map = list[i]->l_real;
/* Here come the extra test needed for `_dl_lookup_symbol_skip'. */
@@ -110,7 +378,7 @@ do_lookup_x (const char *undef_name, uint_fast32_t new_hash,
continue;
/* Print some debugging info if wanted. */
- if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_SYMBOLS, 0))
+ if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_SYMBOLS))
_dl_debug_printf ("symbol=%s; lookup in file=%s [%lu]\n",
undef_name, DSO_FILENAME (map->l_name),
map->l_ns);
@@ -119,111 +387,17 @@ do_lookup_x (const char *undef_name, uint_fast32_t new_hash,
if (map->l_nbuckets == 0)
continue;
+ Elf_Symndx symidx;
+ int num_versions = 0;
+ const ElfW(Sym) *versioned_sym = NULL;
+
/* The tables for this map. */
const ElfW(Sym) *symtab = (const void *) D_PTR (map, l_info[DT_SYMTAB]);
const char *strtab = (const void *) D_PTR (map, l_info[DT_STRTAB]);
-
- /* Nested routine to check whether the symbol matches. */
- const ElfW(Sym) *
- __attribute_noinline__
- check_match (const ElfW(Sym) *sym)
- {
- unsigned int stt = ELFW(ST_TYPE) (sym->st_info);
- assert (ELF_RTYPE_CLASS_PLT == 1);
- if (__builtin_expect ((sym->st_value == 0 /* No value. */
- && stt != STT_TLS)
- || (type_class & (sym->st_shndx == SHN_UNDEF)),
- 0))
- return NULL;
-
- /* Ignore all but STT_NOTYPE, STT_OBJECT, STT_FUNC,
- STT_COMMON, STT_TLS, and STT_GNU_IFUNC since these are no
- code/data definitions. */
-#define ALLOWED_STT \
- ((1 << STT_NOTYPE) | (1 << STT_OBJECT) | (1 << STT_FUNC) \
- | (1 << STT_COMMON) | (1 << STT_TLS) | (1 << STT_GNU_IFUNC))
- if (__builtin_expect (((1 << stt) & ALLOWED_STT) == 0, 0))
- return NULL;
-
- if (sym != ref && strcmp (strtab + sym->st_name, undef_name))
- /* Not the symbol we are looking for. */
- return NULL;
-
- const ElfW(Half) *verstab = map->l_versyms;
- if (version != NULL)
- {
- if (__builtin_expect (verstab == NULL, 0))
- {
- /* We need a versioned symbol but haven't found any. If
- this is the object which is referenced in the verneed
- entry it is a bug in the library since a symbol must
- not simply disappear.
-
- It would also be a bug in the object since it means that
- the list of required versions is incomplete and so the
- tests in dl-version.c haven't found a problem.*/
- assert (version->filename == NULL
- || ! _dl_name_match_p (version->filename, map));
-
- /* Otherwise we accept the symbol. */
- }
- else
- {
- /* We can match the version information or use the
- default one if it is not hidden. */
- ElfW(Half) ndx = verstab[symidx] & 0x7fff;
- if ((map->l_versions[ndx].hash != version->hash
- || strcmp (map->l_versions[ndx].name, version->name))
- && (version->hidden || map->l_versions[ndx].hash
- || (verstab[symidx] & 0x8000)))
- /* It's not the version we want. */
- return NULL;
- }
- }
- else
- {
- /* No specific version is selected. There are two ways we
- can got here:
-
- - a binary which does not include versioning information
- is loaded
-
- - dlsym() instead of dlvsym() is used to get a symbol which
- might exist in more than one form
-
- If the library does not provide symbol version information
- there is no problem at all: we simply use the symbol if it
- is defined.
-
- These two lookups need to be handled differently if the
- library defines versions. In the case of the old
- unversioned application the oldest (default) version
- should be used. In case of a dlsym() call the latest and
- public interface should be returned. */
- if (verstab != NULL)
- {
- if ((verstab[symidx] & 0x7fff)
- >= ((flags & DL_LOOKUP_RETURN_NEWEST) ? 2 : 3))
- {
- /* Don't accept hidden symbols. */
- if ((verstab[symidx] & 0x8000) == 0
- && num_versions++ == 0)
- /* No version so far. */
- versioned_sym = sym;
-
- return NULL;
- }
- }
- }
-
- /* There cannot be another entry for this symbol so stop here. */
- return sym;
- }
-
const ElfW(Sym) *sym;
const ElfW(Addr) *bitmask = map->l_gnu_bitmask;
- if (__builtin_expect (bitmask != NULL, 1))
+ if (__glibc_likely (bitmask != NULL))
{
ElfW(Addr) bitmask_word
= bitmask[(new_hash / __ELF_NATIVE_CLASS)
@@ -233,8 +407,8 @@ do_lookup_x (const char *undef_name, uint_fast32_t new_hash,
unsigned int hashbit2 = ((new_hash >> map->l_gnu_shift)
& (__ELF_NATIVE_CLASS - 1));
- if (__builtin_expect ((bitmask_word >> hashbit1)
- & (bitmask_word >> hashbit2) & 1, 0))
+ if (__glibc_unlikely ((bitmask_word >> hashbit1)
+ & (bitmask_word >> hashbit2) & 1))
{
Elf32_Word bucket = map->l_gnu_buckets[new_hash
% map->l_nbuckets];
@@ -246,7 +420,10 @@ do_lookup_x (const char *undef_name, uint_fast32_t new_hash,
if (((*hasharr ^ new_hash) >> 1) == 0)
{
symidx = hasharr - map->l_gnu_chain_zero;
- sym = check_match (&symtab[symidx]);
+ sym = check_match (undef_name, ref, version, flags,
+ type_class, &symtab[symidx], symidx,
+ strtab, map, &versioned_sym,
+ &num_versions);
if (sym != NULL)
goto found_it;
}
@@ -268,7 +445,10 @@ do_lookup_x (const char *undef_name, uint_fast32_t new_hash,
symidx != STN_UNDEF;
symidx = map->l_chain[symidx])
{
- sym = check_match (&symtab[symidx]);
+ sym = check_match (undef_name, ref, version, flags,
+ type_class, &symtab[symidx], symidx,
+ strtab, map, &versioned_sym,
+ &num_versions);
if (sym != NULL)
goto found_it;
}
@@ -283,11 +463,64 @@ do_lookup_x (const char *undef_name, uint_fast32_t new_hash,
if (sym != NULL)
{
found_it:
- switch (__builtin_expect (ELFW(ST_BIND) (sym->st_info), STB_GLOBAL))
+ /* When UNDEF_MAP is NULL, which indicates we are called from
+ do_lookup_x on relocation against protected data, we skip
+ the data definion in the executable from copy reloc. */
+ if (ELF_RTYPE_CLASS_EXTERN_PROTECTED_DATA
+ && undef_map == NULL
+ && map->l_type == lt_executable
+ && type_class == ELF_RTYPE_CLASS_EXTERN_PROTECTED_DATA)
+ {
+ const ElfW(Sym) *s;
+ unsigned int i;
+
+#if ! ELF_MACHINE_NO_RELA
+ if (map->l_info[DT_RELA] != NULL
+ && map->l_info[DT_RELASZ] != NULL
+ && map->l_info[DT_RELASZ]->d_un.d_val != 0)
+ {
+ const ElfW(Rela) *rela
+ = (const ElfW(Rela) *) D_PTR (map, l_info[DT_RELA]);
+ unsigned int rela_count
+ = map->l_info[DT_RELASZ]->d_un.d_val / sizeof (*rela);
+
+ for (i = 0; i < rela_count; i++, rela++)
+ if (elf_machine_type_class (ELFW(R_TYPE) (rela->r_info))
+ == ELF_RTYPE_CLASS_COPY)
+ {
+ s = &symtab[ELFW(R_SYM) (rela->r_info)];
+ if (!strcmp (strtab + s->st_name, undef_name))
+ goto skip;
+ }
+ }
+#endif
+#if ! ELF_MACHINE_NO_REL
+ if (map->l_info[DT_REL] != NULL
+ && map->l_info[DT_RELSZ] != NULL
+ && map->l_info[DT_RELSZ]->d_un.d_val != 0)
+ {
+ const ElfW(Rel) *rel
+ = (const ElfW(Rel) *) D_PTR (map, l_info[DT_REL]);
+ unsigned int rel_count
+ = map->l_info[DT_RELSZ]->d_un.d_val / sizeof (*rel);
+
+ for (i = 0; i < rel_count; i++, rel++)
+ if (elf_machine_type_class (ELFW(R_TYPE) (rel->r_info))
+ == ELF_RTYPE_CLASS_COPY)
+ {
+ s = &symtab[ELFW(R_SYM) (rel->r_info)];
+ if (!strcmp (strtab + s->st_name, undef_name))
+ goto skip;
+ }
+ }
+#endif
+ }
+
+ switch (ELFW(ST_BIND) (sym->st_info))
{
case STB_WEAK:
/* Weak definition. Use this value if we don't find another. */
- if (__builtin_expect (GLRO(dl_dynamic_weak), 0))
+ if (__glibc_unlikely (GLRO(dl_dynamic_weak)))
{
if (! result->s)
{
@@ -298,157 +531,15 @@ do_lookup_x (const char *undef_name, uint_fast32_t new_hash,
}
/* FALLTHROUGH */
case STB_GLOBAL:
- success:
/* Global definition. Just what we need. */
result->s = sym;
result->m = (struct link_map *) map;
return 1;
case STB_GNU_UNIQUE:;
- /* We have to determine whether we already found a
- symbol with this name before. If not then we have to
- add it to the search table. If we already found a
- definition we have to use it. */
- void enter (struct unique_sym *table, size_t size,
- unsigned int hash, const char *name,
- const ElfW(Sym) *sym, const struct link_map *map)
- {
- size_t idx = hash % size;
- size_t hash2 = 1 + hash % (size - 2);
- while (table[idx].name != NULL)
- {
- idx += hash2;
- if (idx >= size)
- idx -= size;
- }
-
- table[idx].hashval = hash;
- table[idx].name = name;
- table[idx].sym = sym;
- table[idx].map = map;
- }
-
- struct unique_sym_table *tab
- = &GL(dl_ns)[map->l_ns]._ns_unique_sym_table;
-
- __rtld_lock_lock_recursive (tab->lock);
-
- struct unique_sym *entries = tab->entries;
- size_t size = tab->size;
- if (entries != NULL)
- {
- size_t idx = new_hash % size;
- size_t hash2 = 1 + new_hash % (size - 2);
- while (1)
- {
- if (entries[idx].hashval == new_hash
- && strcmp (entries[idx].name, undef_name) == 0)
- {
- if ((type_class & ELF_RTYPE_CLASS_COPY) != 0)
- {
- /* We possibly have to initialize the central
- copy from the copy addressed through the
- relocation. */
- result->s = sym;
- result->m = (struct link_map *) map;
- }
- else
- {
- result->s = entries[idx].sym;
- result->m = (struct link_map *) entries[idx].map;
- }
- __rtld_lock_unlock_recursive (tab->lock);
- return 1;
- }
-
- if (entries[idx].name == NULL)
- break;
-
- idx += hash2;
- if (idx >= size)
- idx -= size;
- }
-
- if (size * 3 <= tab->n_elements * 4)
- {
- /* Expand the table. */
-#ifdef RTLD_CHECK_FOREIGN_CALL
- /* This must not happen during runtime relocations. */
- assert (!RTLD_CHECK_FOREIGN_CALL);
-#endif
- size_t newsize = _dl_higher_prime_number (size + 1);
- struct unique_sym *newentries
- = calloc (sizeof (struct unique_sym), newsize);
- if (newentries == NULL)
- {
- nomem:
- __rtld_lock_unlock_recursive (tab->lock);
- _dl_fatal_printf ("out of memory\n");
- }
-
- for (idx = 0; idx < size; ++idx)
- if (entries[idx].name != NULL)
- enter (newentries, newsize, entries[idx].hashval,
- entries[idx].name, entries[idx].sym,
- entries[idx].map);
-
- tab->free (entries);
- tab->size = newsize;
- size = newsize;
- entries = tab->entries = newentries;
- tab->free = free;
- }
- }
- else
- {
-#ifdef RTLD_CHECK_FOREIGN_CALL
- /* This must not happen during runtime relocations. */
- assert (!RTLD_CHECK_FOREIGN_CALL);
-#endif
-
-#ifdef SHARED
- /* If tab->entries is NULL, but tab->size is not, it means
- this is the second, conflict finding, lookup for
- LD_TRACE_PRELINKING in _dl_debug_bindings. Don't
- allocate anything and don't enter anything into the
- hash table. */
- if (__builtin_expect (tab->size, 0))
- {
- assert (GLRO(dl_debug_mask) & DL_DEBUG_PRELINK);
- __rtld_lock_unlock_recursive (tab->lock);
- goto success;
- }
-#endif
-
-#define INITIAL_NUNIQUE_SYM_TABLE 31
- size = INITIAL_NUNIQUE_SYM_TABLE;
- entries = calloc (sizeof (struct unique_sym), size);
- if (entries == NULL)
- goto nomem;
-
- tab->entries = entries;
- tab->size = size;
- tab->free = free;
- }
-
- if ((type_class & ELF_RTYPE_CLASS_COPY) != 0)
- enter (entries, size, new_hash, strtab + sym->st_name, ref,
- undef_map);
- else
- {
- enter (entries, size, new_hash, strtab + sym->st_name, sym,
- map);
-
- if (map->l_type == lt_loaded)
- /* Make sure we don't unload this object by
- setting the appropriate flag. */
- ((struct link_map *) map)->l_flags_1 |= DF_1_NODELETE;
- }
- ++tab->n_elements;
-
- __rtld_lock_unlock_recursive (tab->lock);
-
- goto success;
+ do_lookup_unique (undef_name, new_hash, map, result, type_class,
+ sym, strtab, ref, undef_map);
+ return 1;
default:
/* Local symbols are ignored. */
@@ -456,10 +547,11 @@ do_lookup_x (const char *undef_name, uint_fast32_t new_hash,
}
}
+skip:
/* If this current map is the one mentioned in the verneed entry
and we have not found a weak entry, it is a bug. */
if (symidx == STN_UNDEF && version != NULL && version->filename != NULL
- && __builtin_expect (_dl_name_match_p (version->filename, map), 0))
+ && __glibc_unlikely (_dl_name_match_p (version->filename, map)))
return -1;
}
while (++i < n);
@@ -530,7 +622,7 @@ add_dependency (struct link_map *undef_map, struct link_map *map, int flags)
unsigned long long serial = map->l_serial;
/* Make sure nobody can unload the object while we are at it. */
- if (__builtin_expect (flags & DL_LOOKUP_GSCOPE_LOCK, 0))
+ if (__glibc_unlikely (flags & DL_LOOKUP_GSCOPE_LOCK))
{
/* We can't just call __rtld_lock_lock_recursive (GL(dl_load_lock))
here, that can result in ABBA deadlock. */
@@ -617,7 +709,7 @@ add_dependency (struct link_map *undef_map, struct link_map *map, int flags)
}
/* Add the reference now. */
- if (__builtin_expect (l_reldepsact >= undef_map->l_reldepsmax, 0))
+ if (__glibc_unlikely (l_reldepsact >= undef_map->l_reldepsmax))
{
/* Allocate more memory for the dependency list. Since this
can never happen during the startup phase we can use
@@ -663,7 +755,7 @@ add_dependency (struct link_map *undef_map, struct link_map *map, int flags)
}
/* Display information if we are debugging. */
- if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_FILES, 0))
+ if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES))
_dl_debug_printf ("\
\nfile=%s [%lu]; needed by %s [%lu] (relocation dependency)\n\n",
DSO_FILENAME (map->l_name),
@@ -679,7 +771,7 @@ add_dependency (struct link_map *undef_map, struct link_map *map, int flags)
/* Release the lock. */
__rtld_lock_unlock_recursive (GL(dl_load_lock));
- if (__builtin_expect (flags & DL_LOOKUP_GSCOPE_LOCK, 0))
+ if (__glibc_unlikely (flags & DL_LOOKUP_GSCOPE_LOCK))
THREAD_GSCOPE_SET_FLAG ();
return result;
@@ -726,7 +818,7 @@ _dl_lookup_symbol_x (const char *undef_name, struct link_map *undef_map,
== 0);
size_t i = 0;
- if (__builtin_expect (skip_map != NULL, 0))
+ if (__glibc_unlikely (skip_map != NULL))
/* Search the relevant loaded objects for a definition. */
while ((*scope)->r_list[i] != skip_map)
++i;
@@ -740,7 +832,7 @@ _dl_lookup_symbol_x (const char *undef_name, struct link_map *undef_map,
if (res > 0)
break;
- if (__builtin_expect (res, 0) < 0 && skip_map == NULL)
+ if (__glibc_unlikely (res < 0) && skip_map == NULL)
{
/* Oh, oh. The file named in the relocation entry does not
contain the needed symbol. This code is never reached
@@ -763,7 +855,7 @@ _dl_lookup_symbol_x (const char *undef_name, struct link_map *undef_map,
}
}
- if (__builtin_expect (current_value.s == NULL, 0))
+ if (__glibc_unlikely (current_value.s == NULL))
{
if ((*ref == NULL || ELFW(ST_BIND) ((*ref)->st_info) != STB_WEAK)
&& skip_map == NULL
@@ -778,7 +870,7 @@ _dl_lookup_symbol_x (const char *undef_name, struct link_map *undef_map,
/* XXX We cannot translate the message. */
_dl_signal_cerror (0, DSO_FILENAME (reference_name),
N_("symbol lookup error"),
- make_string (undefined_msg, undef_name,
+ make_string ("undefined symbol: ", undef_name,
versionstr, versionname));
}
*ref = NULL;
@@ -787,7 +879,7 @@ _dl_lookup_symbol_x (const char *undef_name, struct link_map *undef_map,
int protected = (*ref
&& ELFW(ST_VISIBILITY) ((*ref)->st_other) == STV_PROTECTED);
- if (__builtin_expect (protected != 0, 0))
+ if (__glibc_unlikely (protected != 0))
{
/* It is very tricky. We need to figure out what value to
return for the protected symbol. */
@@ -806,7 +898,12 @@ _dl_lookup_symbol_x (const char *undef_name, struct link_map *undef_map,
for (scope = symbol_scope; *scope != NULL; i = 0, ++scope)
if (do_lookup_x (undef_name, new_hash, &old_hash, *ref,
&protected_value, *scope, i, version, flags,
- skip_map, ELF_RTYPE_CLASS_PLT, NULL) != 0)
+ skip_map,
+ (ELF_RTYPE_CLASS_EXTERN_PROTECTED_DATA
+ && ELFW(ST_TYPE) ((*ref)->st_info) == STT_OBJECT
+ && type_class == ELF_RTYPE_CLASS_EXTERN_PROTECTED_DATA)
+ ? ELF_RTYPE_CLASS_EXTERN_PROTECTED_DATA
+ : ELF_RTYPE_CLASS_PLT, NULL) != 0)
break;
if (protected_value.s != NULL && protected_value.m != undef_map)
@@ -821,7 +918,7 @@ _dl_lookup_symbol_x (const char *undef_name, struct link_map *undef_map,
in the global scope which was dynamically loaded. In this case
we have to prevent the latter from being unloaded unless the
UNDEF_MAP object is also unloaded. */
- if (__builtin_expect (current_value.m->l_type == lt_loaded, 0)
+ if (__glibc_unlikely (current_value.m->l_type == lt_loaded)
/* Don't do this for explicit lookups as opposed to implicit
runtime lookups. */
&& (flags & DL_LOOKUP_ADD_DEPENDENCY) != 0
@@ -835,11 +932,11 @@ _dl_lookup_symbol_x (const char *undef_name, struct link_map *undef_map,
version, type_class, flags, skip_map);
/* The object is used. */
- if (__builtin_expect (current_value.m->l_used == 0, 0))
+ if (__glibc_unlikely (current_value.m->l_used == 0))
current_value.m->l_used = 1;
- if (__builtin_expect (GLRO(dl_debug_mask)
- & (DL_DEBUG_BINDINGS|DL_DEBUG_PRELINK), 0))
+ if (__glibc_unlikely (GLRO(dl_debug_mask)
+ & (DL_DEBUG_BINDINGS|DL_DEBUG_PRELINK)))
_dl_debug_bindings (undef_name, undef_map, ref,
&current_value, version, type_class, protected);
@@ -856,9 +953,9 @@ _dl_setup_hash (struct link_map *map)
{
Elf_Symndx *hash;
- if (__builtin_expect (map->l_info[DT_ADDRTAGIDX (DT_GNU_HASH) + DT_NUM
+ if (__glibc_likely (map->l_info[DT_ADDRTAGIDX (DT_GNU_HASH) + DT_NUM
+ DT_THISPROCNUM + DT_VERSIONTAGNUM
- + DT_EXTRANUM + DT_VALNUM] != NULL, 1))
+ + DT_EXTRANUM + DT_VALNUM] != NULL))
{
Elf32_Word *hash32
= (void *) D_PTR (map, l_info[DT_ADDRTAGIDX (DT_GNU_HASH) + DT_NUM
@@ -937,10 +1034,10 @@ _dl_debug_bindings (const char *undef_name, struct link_map *undef_map,
type_class, undef_map);
if (val.s != value->s || val.m != value->m)
conflict = 1;
- else if (__builtin_expect (undef_map->l_symbolic_in_local_scope, 0)
+ else if (__glibc_unlikely (undef_map->l_symbolic_in_local_scope)
&& val.s
- && __builtin_expect (ELFW(ST_BIND) (val.s->st_info),
- STB_GLOBAL) == STB_GNU_UNIQUE)
+ && __glibc_unlikely (ELFW(ST_BIND) (val.s->st_info)
+ == STB_GNU_UNIQUE))
{
/* If it is STB_GNU_UNIQUE and undef_map's l_local_scope
contains any DT_SYMBOLIC libraries, unfortunately there
@@ -974,11 +1071,11 @@ _dl_debug_bindings (const char *undef_name, struct link_map *undef_map,
if (value->s)
{
- if (__builtin_expect (ELFW(ST_TYPE) (value->s->st_info)
- == STT_TLS, 0))
+ if (__glibc_unlikely (ELFW(ST_TYPE) (value->s->st_info)
+ == STT_TLS))
type_class = 4;
- else if (__builtin_expect (ELFW(ST_TYPE) (value->s->st_info)
- == STT_GNU_IFUNC, 0))
+ else if (__glibc_unlikely (ELFW(ST_TYPE) (value->s->st_info)
+ == STT_GNU_IFUNC))
type_class |= 8;
}
diff --git a/elf/dl-machine-reject-phdr.h b/elf/dl-machine-reject-phdr.h
new file mode 100644
index 0000000000..f071c69b12
--- /dev/null
+++ b/elf/dl-machine-reject-phdr.h
@@ -0,0 +1,34 @@
+/* Machine-dependent program header inspection for the ELF loader.
+ Copyright (C) 2014-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/>. */
+
+#ifndef _DL_MACHINE_REJECT_PHDR_H
+#define _DL_MACHINE_REJECT_PHDR_H 1
+
+#include <stdbool.h>
+
+/* Return true iff ELF program headers are incompatible with the running
+ host. */
+static inline bool
+elf_machine_reject_phdr_p (const ElfW(Phdr) *phdr, uint_fast16_t phnum,
+ const char *buf, size_t len, struct link_map *map,
+ int fd)
+{
+ return false;
+}
+
+#endif /* dl-machine-reject-phdr.h */
diff --git a/elf/dl-map-segments.h b/elf/dl-map-segments.h
new file mode 100644
index 0000000000..baaa8135df
--- /dev/null
+++ b/elf/dl-map-segments.h
@@ -0,0 +1,153 @@
+/* Map in a shared object's segments. Generic version.
+ Copyright (C) 1995-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 <dl-load.h>
+
+/* This implementation assumes (as does the corresponding implementation
+ of _dl_unmap_segments, in dl-unmap-segments.h) that shared objects
+ are always laid out with all segments contiguous (or with gaps
+ between them small enough that it's preferable to reserve all whole
+ pages inside the gaps with PROT_NONE mappings rather than permitting
+ other use of those parts of the address space). */
+
+static __always_inline const char *
+_dl_map_segments (struct link_map *l, int fd,
+ const ElfW(Ehdr) *header, int type,
+ const struct loadcmd loadcmds[], size_t nloadcmds,
+ const size_t maplength, bool has_holes,
+ struct link_map *loader)
+{
+ const struct loadcmd *c = loadcmds;
+
+ if (__glibc_likely (type == ET_DYN))
+ {
+ /* This is a position-independent shared object. We can let the
+ kernel map it anywhere it likes, but we must have space for all
+ the segments in their specified positions relative to the first.
+ So we map the first segment without MAP_FIXED, but with its
+ extent increased to cover all the segments. Then we remove
+ access from excess portion, and there is known sufficient space
+ there to remap from the later segments.
+
+ As a refinement, sometimes we have an address that we would
+ prefer to map such objects at; but this is only a preference,
+ the OS can do whatever it likes. */
+ ElfW(Addr) mappref
+ = (ELF_PREFERRED_ADDRESS (loader, maplength,
+ c->mapstart & GLRO(dl_use_load_bias))
+ - MAP_BASE_ADDR (l));
+
+ /* Remember which part of the address space this object uses. */
+ l->l_map_start = (ElfW(Addr)) __mmap ((void *) mappref, maplength,
+ c->prot,
+ MAP_COPY|MAP_FILE,
+ fd, c->mapoff);
+ if (__glibc_unlikely ((void *) l->l_map_start == MAP_FAILED))
+ return DL_MAP_SEGMENTS_ERROR_MAP_SEGMENT;
+
+ l->l_map_end = l->l_map_start + maplength;
+ l->l_addr = l->l_map_start - c->mapstart;
+
+ if (has_holes)
+ /* Change protection on the excess portion to disallow all access;
+ the portions we do not remap later will be inaccessible as if
+ unallocated. Then jump into the normal segment-mapping loop to
+ handle the portion of the segment past the end of the file
+ mapping. */
+ __mprotect ((caddr_t) (l->l_addr + c->mapend),
+ loadcmds[nloadcmds - 1].mapstart - c->mapend,
+ PROT_NONE);
+
+ l->l_contiguous = 1;
+
+ goto postmap;
+ }
+
+ /* Remember which part of the address space this object uses. */
+ l->l_map_start = c->mapstart + l->l_addr;
+ l->l_map_end = l->l_map_start + maplength;
+ l->l_contiguous = !has_holes;
+
+ while (c < &loadcmds[nloadcmds])
+ {
+ if (c->mapend > c->mapstart
+ /* Map the segment contents from the file. */
+ && (__mmap ((void *) (l->l_addr + c->mapstart),
+ c->mapend - c->mapstart, c->prot,
+ MAP_FIXED|MAP_COPY|MAP_FILE,
+ fd, c->mapoff)
+ == MAP_FAILED))
+ return DL_MAP_SEGMENTS_ERROR_MAP_SEGMENT;
+
+ postmap:
+ _dl_postprocess_loadcmd (l, header, c);
+
+ if (c->allocend > c->dataend)
+ {
+ /* Extra zero pages should appear at the end of this segment,
+ after the data mapped from the file. */
+ ElfW(Addr) zero, zeroend, zeropage;
+
+ zero = l->l_addr + c->dataend;
+ zeroend = l->l_addr + c->allocend;
+ zeropage = ((zero + GLRO(dl_pagesize) - 1)
+ & ~(GLRO(dl_pagesize) - 1));
+
+ if (zeroend < zeropage)
+ /* All the extra data is in the last page of the segment.
+ We can just zero it. */
+ zeropage = zeroend;
+
+ if (zeropage > zero)
+ {
+ /* Zero the final part of the last page of the segment. */
+ if (__glibc_unlikely ((c->prot & PROT_WRITE) == 0))
+ {
+ /* Dag nab it. */
+ if (__mprotect ((caddr_t) (zero
+ & ~(GLRO(dl_pagesize) - 1)),
+ GLRO(dl_pagesize), c->prot|PROT_WRITE) < 0)
+ return DL_MAP_SEGMENTS_ERROR_MPROTECT;
+ }
+ memset ((void *) zero, '\0', zeropage - zero);
+ if (__glibc_unlikely ((c->prot & PROT_WRITE) == 0))
+ __mprotect ((caddr_t) (zero & ~(GLRO(dl_pagesize) - 1)),
+ GLRO(dl_pagesize), c->prot);
+ }
+
+ if (zeroend > zeropage)
+ {
+ /* Map the remaining zero pages in from the zero fill FD. */
+ caddr_t mapat;
+ mapat = __mmap ((caddr_t) zeropage, zeroend - zeropage,
+ c->prot, MAP_ANON|MAP_PRIVATE|MAP_FIXED,
+ -1, 0);
+ if (__glibc_unlikely (mapat == MAP_FAILED))
+ return DL_MAP_SEGMENTS_ERROR_MAP_ZERO_FILL;
+ }
+ }
+
+ ++c;
+ }
+
+ /* Notify ELF_PREFERRED_ADDRESS that we have to load this one
+ fixed. */
+ ELF_FIXED_ADDRESS (loader, c->mapstart);
+
+ return NULL;
+}
diff --git a/elf/dl-minimal.c b/elf/dl-minimal.c
index 22d0b3c8af..ec7fe88d30 100644
--- a/elf/dl-minimal.c
+++ b/elf/dl-minimal.c
@@ -1,5 +1,5 @@
/* Minimal replacements for basic facilities used in the dynamic linker.
- Copyright (C) 1995-2014 Free Software Foundation, Inc.
+ Copyright (C) 1995-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
@@ -18,6 +18,7 @@
#include <errno.h>
#include <limits.h>
+#include <stdio.h>
#include <string.h>
#include <tls.h>
#include <unistd.h>
@@ -68,7 +69,7 @@ __libc_memalign (size_t align, size_t n)
/* Insufficient space left; allocate another page. */
caddr_t page;
size_t nup = (n + GLRO(dl_pagesize) - 1) & ~(GLRO(dl_pagesize) - 1);
- if (__builtin_expect (nup == 0, 0))
+ if (__glibc_unlikely (nup == 0))
{
if (n)
return NULL;
@@ -193,8 +194,22 @@ __strerror_r (int errnum, char *buf, size_t buflen)
return msg;
}
-#ifndef NDEBUG
+void
+__libc_fatal (const char *message)
+{
+ _dl_fatal_printf ("%s", message);
+}
+rtld_hidden_def (__libc_fatal)
+void
+__attribute__ ((noreturn))
+__chk_fail (void)
+{
+ _exit (127);
+}
+rtld_hidden_def (__chk_fail)
+
+#ifndef NDEBUG
/* Define (weakly) our own assert failure function which doesn't use stdio.
If we are linked into the user program (-ldl), the normal __assert_fail
defn can override this one. */
@@ -209,7 +224,7 @@ Inconsistency detected by ld.so: %s: %u: %s%sAssertion `%s' failed!\n",
assertion);
}
-rtld_hidden_weak(__assert_fail)
+rtld_hidden_weak (__assert_fail)
void weak_function
__assert_perror_fail (int errnum,
@@ -225,7 +240,7 @@ Inconsistency detected by ld.so: %s: %u: %s%sUnexpected error: %s.\n",
}
rtld_hidden_weak (__assert_perror_fail)
#endif
-
+
unsigned long int weak_function
__strtoul_internal (const char *nptr, char **endptr, int base, int group)
{
@@ -324,7 +339,11 @@ _itoa (value, buflim, base, upper_case)
return buflim;
}
-
+/* The '_itoa_lower_digits' variable in libc.so is able to handle bases
+ up to 36. We don't need this here. */
+const char _itoa_lower_digits[16] = "0123456789abcdef";
+rtld_hidden_data_def (_itoa_lower_digits)
+
/* The following is not a complete strsep implementation. It cannot
handle empty delimiter strings. But this isn't necessary for the
execution of ld.so. */
@@ -367,16 +386,3 @@ __strsep (char **stringp, const char *delim)
}
weak_alias (__strsep, strsep)
strong_alias (__strsep, __strsep_g)
-
-void
-__attribute__ ((noreturn))
-__chk_fail (void)
-{
- _exit (127);
-}
-rtld_hidden_def (__chk_fail)
-
-/* The '_itoa_lower_digits' variable in libc.so is able to handle bases
- up to 36. We don't need this here. */
-const char _itoa_lower_digits[16] = "0123456789abcdef";
-rtld_hidden_data_def (_itoa_lower_digits)
diff --git a/elf/dl-misc.c b/elf/dl-misc.c
index 8fd67100e3..2c8b6c5d40 100644
--- a/elf/dl-misc.c
+++ b/elf/dl-misc.c
@@ -1,5 +1,5 @@
/* Miscellaneous support functions for dynamic linker
- Copyright (C) 1997-2014 Free Software Foundation, Inc.
+ Copyright (C) 1997-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
diff --git a/elf/dl-object.c b/elf/dl-object.c
index afd80a6bd3..1d58bbc48c 100644
--- a/elf/dl-object.c
+++ b/elf/dl-object.c
@@ -1,5 +1,5 @@
/* Storage management for the chain of loaded shared objects.
- Copyright (C) 1995-2014 Free Software Foundation, Inc.
+ Copyright (C) 1995-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
diff --git a/elf/dl-open.c b/elf/dl-open.c
index a9ca6b3b44..2db1c02148 100644
--- a/elf/dl-open.c
+++ b/elf/dl-open.c
@@ -1,5 +1,5 @@
/* Load a shared object at runtime, relocate it, and run its initializer.
- Copyright (C) 1996-2014 Free Software Foundation, Inc.
+ Copyright (C) 1996-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
@@ -147,7 +147,7 @@ add_to_global (struct link_map *new)
ns->_ns_main_searchlist->r_list[new_nlist++] = map;
/* We modify the global scope. Report this. */
- if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_SCOPES, 0))
+ if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_SCOPES))
_dl_debug_printf ("\nadd %s [%lu] to global scope\n",
map->l_name, map->l_ns);
}
@@ -211,19 +211,27 @@ dl_open_worker (void *a)
struct link_map *l = _dl_find_dso_for_object ((ElfW(Addr)) caller_dlopen);
if (l)
- call_map = l;
+ call_map = l;
if (args->nsid == __LM_ID_CALLER)
args->nsid = call_map->l_ns;
}
- assert (_dl_debug_initialize (0, args->nsid)->r_state == RT_CONSISTENT);
+ /* One might be tempted to assert that we are RT_CONSISTENT at this point, but that
+ may not be true if this is a recursive call to dlopen. */
+ _dl_debug_initialize (0, args->nsid);
/* Load the named object. */
struct link_map *new;
args->map = new = _dl_map_object (call_map, file, lt_loaded, 0,
mode | __RTLD_CALLMAP, args->nsid);
+ /* Mark the object as not deletable if the RTLD_NODELETE flags was passed.
+ Do this early so that we don't skip marking the object if it was
+ already loaded. */
+ if (__glibc_unlikely (mode & RTLD_NODELETE))
+ new->l_flags_1 |= DF_1_NODELETE;
+
/* If the pointer returned is NULL this means the RTLD_NOLOAD flag is
set and the object is not already loaded. */
if (new == NULL)
@@ -232,7 +240,7 @@ dl_open_worker (void *a)
return;
}
- if (__builtin_expect (mode & __RTLD_SPROF, 0))
+ if (__glibc_unlikely (mode & __RTLD_SPROF))
/* This happens only if we load a DSO for 'sprof'. */
return;
@@ -240,10 +248,10 @@ dl_open_worker (void *a)
++new->l_direct_opencount;
/* It was already open. */
- if (__builtin_expect (new->l_searchlist.r_list != NULL, 0))
+ if (__glibc_unlikely (new->l_searchlist.r_list != NULL))
{
/* Let the user know about the opencount. */
- if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_FILES, 0))
+ if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES))
_dl_debug_printf ("opening file=%s [%lu]; direct_opencount=%u\n\n",
new->l_name, new->l_ns, new->l_direct_opencount);
@@ -269,7 +277,7 @@ dl_open_worker (void *a)
#ifdef SHARED
/* Auditing checkpoint: we have added all objects. */
- if (__builtin_expect (GLRO(dl_naudit) > 0, 0))
+ if (__glibc_unlikely (GLRO(dl_naudit) > 0))
{
struct link_map *head = GL(dl_ns)[new->l_ns]._ns_loaded;
/* Do not call the functions for any auditing object. */
@@ -294,7 +302,7 @@ dl_open_worker (void *a)
LIBC_PROBE (map_complete, 3, args->nsid, r, new);
/* Print scope information. */
- if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_SCOPES, 0))
+ if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_SCOPES))
_dl_show_scope (new, 0);
/* Only do lazy relocation if `LD_BIND_NOW' is not set. */
@@ -344,7 +352,7 @@ dl_open_worker (void *a)
if (runp != NULL)
/* Look through the dependencies of the object. */
while (*runp != NULL)
- if (__builtin_expect (*runp++ == thisp, 0))
+ if (__glibc_unlikely (*runp++ == thisp))
{
/* Move the current object to the back past the last
object with it as the dependency. */
@@ -391,7 +399,7 @@ dl_open_worker (void *a)
}
#ifdef SHARED
- if (__builtin_expect (GLRO(dl_profile) != NULL, 0))
+ if (__glibc_unlikely (GLRO(dl_profile) != NULL))
{
/* If this here is the shared object which we want to profile
make sure the profile is started. We can find out whether
@@ -444,7 +452,7 @@ dl_open_worker (void *a)
/* Avoid duplicates. */
continue;
- if (__builtin_expect (cnt + 1 >= imap->l_scope_max, 0))
+ if (__glibc_unlikely (cnt + 1 >= imap->l_scope_max))
{
/* The 'r_scope' array is too small. Allocate a new one
dynamically. */
@@ -511,7 +519,7 @@ dl_open_worker (void *a)
}
/* Print scope information. */
- if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_SCOPES, 0))
+ if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_SCOPES))
_dl_show_scope (imap, from_scope);
}
@@ -531,17 +539,7 @@ TLS generation counter wrapped! Please report this."));
&& imap->l_tls_blocksize > 0)
{
/* For static TLS we have to allocate the memory here and
- now. This includes allocating memory in the DTV. But we
- cannot change any DTV other than our own. So, if we
- cannot guarantee that there is room in the DTV we don't
- even try it and fail the load.
-
- XXX We could track the minimum DTV slots allocated in
- all threads. */
- if (! RTLD_SINGLE_THREAD_P && imap->l_tls_modid > DTV_SURPLUS)
- _dl_signal_error (0, "dlopen", NULL, N_("\
-cannot load any more object with static TLS"));
-
+ now, but we can delay updating the DTV. */
imap->l_need_tls_init = 0;
#ifdef SHARED
/* Update the slot information data for at least the
@@ -572,11 +570,6 @@ cannot load any more object with static TLS"));
/* It failed. */
return;
- /* Mark the object as not deletable if the RTLD_NODELETE flags was
- passed. */
- if (__builtin_expect (mode & RTLD_NODELETE, 0))
- new->l_flags_1 |= DF_1_NODELETE;
-
#ifndef SHARED
/* We must be the static _dl_open in libc.a. A static program that
has loaded a dynamic object now has competition. */
@@ -584,7 +577,7 @@ cannot load any more object with static TLS"));
#endif
/* Let the user know about the opencount. */
- if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_FILES, 0))
+ if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES))
_dl_debug_printf ("opening file=%s [%lu]; direct_opencount=%u\n\n",
new->l_name, new->l_ns, new->l_direct_opencount);
}
@@ -601,14 +594,14 @@ _dl_open (const char *file, int mode, const void *caller_dlopen, Lmid_t nsid,
/* Make sure we are alone. */
__rtld_lock_lock_recursive (GL(dl_load_lock));
- if (__builtin_expect (nsid == LM_ID_NEWLM, 0))
+ if (__glibc_unlikely (nsid == LM_ID_NEWLM))
{
/* Find a new namespace. */
for (nsid = 1; DL_NNS > 1 && nsid < GL(dl_nns); ++nsid)
if (GL(dl_ns)[nsid]._ns_loaded == NULL)
break;
- if (__builtin_expect (nsid == DL_NNS, 0))
+ if (__glibc_unlikely (nsid == DL_NNS))
{
/* No more namespace available. */
__rtld_lock_unlock_recursive (GL(dl_load_lock));
@@ -627,8 +620,14 @@ no more namespaces available for dlmopen()"));
/* Never allow loading a DSO in a namespace which is empty. Such
direct placements is only causing problems. Also don't allow
loading into a namespace used for auditing. */
- else if (__builtin_expect (nsid != LM_ID_BASE && nsid != __LM_ID_CALLER, 0)
- && (GL(dl_ns)[nsid]._ns_nloaded == 0
+ else if (__glibc_unlikely (nsid != LM_ID_BASE && nsid != __LM_ID_CALLER)
+ && (__glibc_unlikely (nsid < 0 || nsid >= GL(dl_nns))
+ /* This prevents the [NSID] index expressions from being
+ evaluated, so the compiler won't think that we are
+ accessing an invalid index here in the !SHARED case where
+ DL_NNS is 1 and so any NSID != 0 is invalid. */
+ || DL_NNS == 1
+ || GL(dl_ns)[nsid]._ns_nloaded == 0
|| GL(dl_ns)[nsid]._ns_loaded->l_auditing))
_dl_signal_error (EINVAL, file, NULL,
N_("invalid target namespace in dlmopen()"));
@@ -656,7 +655,7 @@ no more namespaces available for dlmopen()"));
#endif
/* See if an error occurred during loading. */
- if (__builtin_expect (errstring != NULL, 0))
+ if (__glibc_unlikely (errstring != NULL))
{
/* Remove the object from memory. It may be in an inconsistent
state if relocation failed, for example. */
@@ -672,7 +671,7 @@ no more namespaces available for dlmopen()"));
if ((mode & __RTLD_AUDIT) == 0)
GL(dl_tls_dtv_gaps) = true;
- _dl_close_worker (args.map);
+ _dl_close_worker (args.map, true);
}
assert (_dl_debug_initialize (0, args.nsid)->r_state == RT_CONSISTENT);
@@ -737,7 +736,7 @@ _dl_show_scope (struct link_map *l, int from)
_dl_debug_printf ("\n");
}
-#ifdef IS_IN_rtld
+#if IS_IN (rtld)
/* Return non-zero if ADDR lies within one of L's segments. */
int
internal_function
diff --git a/elf/dl-origin.c b/elf/dl-origin.c
index e192939345..206ffb0e95 100644
--- a/elf/dl-origin.c
+++ b/elf/dl-origin.c
@@ -1,5 +1,5 @@
/* Find path of executable.
- Copyright (C) 1998-2014 Free Software Foundation, Inc.
+ Copyright (C) 1998-2015 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
diff --git a/elf/dl-profile.c b/elf/dl-profile.c
index 2fca7fda19..d97a847c9f 100644
--- a/elf/dl-profile.c
+++ b/elf/dl-profile.c
@@ -1,5 +1,5 @@
/* Profiling of shared libraries.
- Copyright (C) 1997-2014 Free Software Foundation, Inc.
+ Copyright (C) 1997-2015 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
Based on the BSD mcount implementation.
@@ -598,4 +598,4 @@ _dl_mcount (ElfW(Addr) frompc, ElfW(Addr) selfpc)
done:
;
}
-INTDEF(_dl_mcount)
+rtld_hidden_def (_dl_mcount)
diff --git a/elf/dl-profstub.c b/elf/dl-profstub.c
index 44e1b75283..a74517dce6 100644
--- a/elf/dl-profstub.c
+++ b/elf/dl-profstub.c
@@ -1,5 +1,5 @@
/* Helper definitions for profiling of shared libraries.
- Copyright (C) 1998-2014 Free Software Foundation, Inc.
+ Copyright (C) 1998-2015 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
diff --git a/elf/dl-reloc.c b/elf/dl-reloc.c
index 1f66fccee2..61252d7697 100644
--- a/elf/dl-reloc.c
+++ b/elf/dl-reloc.c
@@ -1,5 +1,5 @@
/* Relocate a shared object and resolve its references to other loaded objects.
- Copyright (C) 1995-2014 Free Software Foundation, Inc.
+ Copyright (C) 1995-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
@@ -26,6 +26,7 @@
#include <sys/types.h>
#include <_itoa.h>
#include "dynamic-link.h"
+#include <libc-internal.h>
/* Statistics function. */
#ifdef SHARED
@@ -74,9 +75,9 @@ _dl_try_allocate_static_tls (struct link_map *map)
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)
- - map->l_tls_firstbyte_offset
- + map->l_tls_align - 1) & -map->l_tls_align)
+ size_t offset = (ALIGN_UP(GL(dl_tls_static_used)
+ - map->l_tls_firstbyte_offset,
+ map->l_tls_align)
+ map->l_tls_firstbyte_offset);
size_t used = offset + map->l_tls_blocksize;
@@ -136,12 +137,6 @@ _dl_nothread_init_static_tls (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_t *dtv = THREAD_DTV ();
- assert (map->l_tls_modid <= dtv[-1].counter);
- 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);
@@ -183,14 +178,14 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
&& __builtin_expect (l->l_info[DT_BIND_NOW] != NULL, 0))
lazy = 0;
- if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_RELOC, 0))
+ if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_RELOC))
_dl_debug_printf ("\nrelocation processing: %s%s\n",
DSO_FILENAME (l->l_name), lazy ? " (lazy)" : "");
/* DT_TEXTREL is now in level 2 and might phase out at some time.
But we rewrite the DT_FLAGS entry to a DT_TEXTREL entry to make
testing easier and therefore it will be available at all time. */
- if (__builtin_expect (l->l_info[DT_TEXTREL] != NULL, 0))
+ if (__glibc_unlikely (l->l_info[DT_TEXTREL] != NULL))
{
/* Bletch. We must make read-only segments writable
long enough to relocate them. */
@@ -201,11 +196,10 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
struct textrels *newp;
newp = (struct textrels *) alloca (sizeof (*newp));
- newp->len = (((ph->p_vaddr + ph->p_memsz + GLRO(dl_pagesize) - 1)
- & ~(GLRO(dl_pagesize) - 1))
- - (ph->p_vaddr & ~(GLRO(dl_pagesize) - 1)));
- newp->start = ((ph->p_vaddr & ~(GLRO(dl_pagesize) - 1))
- + (caddr_t) l->l_addr);
+ newp->len = ALIGN_UP (ph->p_vaddr + ph->p_memsz, GLRO(dl_pagesize))
+ - ALIGN_DOWN (ph->p_vaddr, GLRO(dl_pagesize));
+ newp->start = PTR_ALIGN_DOWN (ph->p_vaddr, GLRO(dl_pagesize))
+ + (caddr_t) l->l_addr;
if (__mprotect (newp->start, newp->len, PROT_READ|PROT_WRITE) < 0)
{
@@ -264,28 +258,24 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
ELF_DYNAMIC_RELOCATE (l, lazy, consider_profiling, skip_ifunc);
#ifndef PROF
- if (__builtin_expect (consider_profiling, 0))
+ if (__glibc_unlikely (consider_profiling)
+ && l->l_info[DT_PLTRELSZ] != NULL)
{
/* Allocate the array which will contain the already found
relocations. If the shared object lacks a PLT (for example
if it only contains lead function) the l_info[DT_PLTRELSZ]
will be NULL. */
- if (l->l_info[DT_PLTRELSZ] == NULL)
- {
- errstring = N_("%s: no PLTREL found in object %s\n");
- fatal:
- _dl_fatal_printf (errstring,
- RTLD_PROGNAME,
- l->l_name);
- }
+ size_t sizeofrel = l->l_info[DT_PLTREL]->d_un.d_val == DT_RELA
+ ? sizeof (ElfW(Rela))
+ : sizeof (ElfW(Rel));
+ size_t relcount = l->l_info[DT_PLTRELSZ]->d_un.d_val / sizeofrel;
+ l->l_reloc_result = calloc (sizeof (l->l_reloc_result[0]), relcount);
- l->l_reloc_result = calloc (sizeof (l->l_reloc_result[0]),
- l->l_info[DT_PLTRELSZ]->d_un.d_val);
if (l->l_reloc_result == NULL)
{
errstring = N_("\
%s: out of memory to store relocation results for %s\n");
- goto fatal;
+ _dl_fatal_printf (errstring, RTLD_PROGNAME, l->l_name);
}
}
#endif
@@ -320,11 +310,13 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
void internal_function
_dl_protect_relro (struct link_map *l)
{
- ElfW(Addr) start = ((l->l_addr + l->l_relro_addr)
- & ~(GLRO(dl_pagesize) - 1));
- ElfW(Addr) end = ((l->l_addr + l->l_relro_addr + l->l_relro_size)
- & ~(GLRO(dl_pagesize) - 1));
-
+ ElfW(Addr) start = ALIGN_DOWN((l->l_addr
+ + l->l_relro_addr),
+ GLRO(dl_pagesize));
+ ElfW(Addr) end = ALIGN_DOWN((l->l_addr
+ + l->l_relro_addr
+ + l->l_relro_size),
+ GLRO(dl_pagesize));
if (start != end
&& __mprotect ((void *) start, end - start, PROT_READ) < 0)
{
diff --git a/elf/dl-runtime.c b/elf/dl-runtime.c
index 655623b425..bd9a1b1c68 100644
--- a/elf/dl-runtime.c
+++ b/elf/dl-runtime.c
@@ -1,5 +1,5 @@
/* On-demand PLT fixup for shared objects.
- Copyright (C) 1995-2014 Free Software Foundation, Inc.
+ Copyright (C) 1995-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
@@ -29,7 +29,7 @@
#include <dl-irel.h>
-#if (!defined ELF_MACHINE_NO_RELA && !defined ELF_MACHINE_PLT_REL) \
+#if (!ELF_MACHINE_NO_RELA && !defined ELF_MACHINE_PLT_REL) \
|| ELF_MACHINE_NO_REL
# define PLTREL ElfW(Rela)
#else
@@ -142,7 +142,7 @@ _dl_fixup (
value = elf_ifunc_invoke (DL_FIXUP_VALUE_ADDR (value));
/* Finally, fix up the plt itself. */
- if (__builtin_expect (GLRO(dl_bind_not), 0))
+ if (__glibc_unlikely (GLRO(dl_bind_not)))
return value;
return elf_machine_fixup_plt (l, result, reloc, rel_addr, value);
@@ -158,7 +158,7 @@ _dl_profile_fixup (
struct link_map *l, ElfW(Word) reloc_arg,
ElfW(Addr) retaddr, void *regs, long int *framesizep)
{
- void (*mcount_fct) (ElfW(Addr), ElfW(Addr)) = INTUSE(_dl_mcount);
+ void (*mcount_fct) (ElfW(Addr), ElfW(Addr)) = _dl_mcount;
if (l->l_reloc_result == NULL)
{
@@ -347,7 +347,7 @@ _dl_profile_fixup (
#endif
/* Store the result for later runs. */
- if (__builtin_expect (! GLRO(dl_bind_not), 1))
+ if (__glibc_likely (! GLRO(dl_bind_not)))
*resultp = value;
}
diff --git a/elf/dl-scope.c b/elf/dl-scope.c
index e6e06bf9c1..8cfea660b4 100644
--- a/elf/dl-scope.c
+++ b/elf/dl-scope.c
@@ -1,5 +1,5 @@
/* Memory handling for the scope data structures.
- Copyright (C) 2009-2014 Free Software Foundation, Inc.
+ Copyright (C) 2009-2015 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/elf/dl-support.c b/elf/dl-support.c
index 9ace042cbe..0a5e1db246 100644
--- a/elf/dl-support.c
+++ b/elf/dl-support.c
@@ -1,5 +1,5 @@
/* Support for dynamic linking code in static libc.
- Copyright (C) 1996-2014 Free Software Foundation, Inc.
+ Copyright (C) 1996-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
@@ -129,12 +129,6 @@ void *_dl_random;
/* Get architecture specific initializer. */
#include <dl-procinfo.c>
-/* We expect less than a second for relocation. */
-#ifdef HP_SMALL_TIMING_AVAIL
-# undef HP_TIMING_AVAIL
-# define HP_TIMING_AVAIL HP_SMALL_TIMING_AVAIL
-#endif
-
/* Initial value of the CPU clock. */
#ifndef HP_TIMING_NONAVAIL
hp_timing_t _dl_cpuclock_offset;
@@ -316,7 +310,7 @@ _dl_non_dynamic_init (void)
_dl_main_map.l_phdr = GL(dl_phdr);
_dl_main_map.l_phnum = GL(dl_phnum);
- if (HP_TIMING_AVAIL)
+ if (HP_SMALL_TIMING_AVAIL)
HP_TIMING_NOW (_dl_cpuclock_offset);
_dl_verbose = *(getenv ("LD_WARN") ?: "") == '\0' ? 0 : 1;
diff --git a/elf/dl-sym.c b/elf/dl-sym.c
index f00975de77..56fea86fa8 100644
--- a/elf/dl-sym.c
+++ b/elf/dl-sym.c
@@ -1,5 +1,5 @@
/* Look up a symbol in a shared object loaded by `dlopen'.
- Copyright (C) 1999-2014 Free Software Foundation, Inc.
+ Copyright (C) 1999-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
@@ -128,7 +128,7 @@ do_sym (void *handle, const char *name, void *who,
THREAD_GSCOPE_RESET_FLAG ();
- if (__builtin_expect (errstring != NULL, 0))
+ if (__glibc_unlikely (errstring != NULL))
{
/* The lookup was unsuccessful. Rethrow the error. */
char *errstring_dup = strdupa (errstring);
@@ -145,7 +145,7 @@ do_sym (void *handle, const char *name, void *who,
}
else if (handle == RTLD_NEXT)
{
- if (__builtin_expect (match == GL(dl_ns)[LM_ID_BASE]._ns_loaded, 0))
+ if (__glibc_unlikely (match == GL(dl_ns)[LM_ID_BASE]._ns_loaded))
{
if (match == NULL
|| caller < match->l_map_start
@@ -183,7 +183,7 @@ RTLD_NEXT used in code not dynamically loaded"));
value = DL_SYMBOL_ADDRESS (result, ref);
/* Resolve indirect function address. */
- if (__builtin_expect (ELFW(ST_TYPE) (ref->st_info) == STT_GNU_IFUNC, 0))
+ if (__glibc_unlikely (ELFW(ST_TYPE) (ref->st_info) == STT_GNU_IFUNC))
{
DL_FIXUP_VALUE_TYPE fixup
= DL_FIXUP_MAKE_VALUE (result, (ElfW(Addr)) value);
@@ -195,7 +195,7 @@ RTLD_NEXT used in code not dynamically loaded"));
/* Auditing checkpoint: we have a new binding. Provide the
auditing libraries the possibility to change the value and
tell us whether further auditing is wanted. */
- if (__builtin_expect (GLRO(dl_naudit) > 0, 0))
+ if (__glibc_unlikely (GLRO(dl_naudit) > 0))
{
const char *strtab = (const char *) D_PTR (result,
l_info[DT_STRTAB]);
diff --git a/elf/dl-symaddr.c b/elf/dl-symaddr.c
index b73a5f30b0..e18a203184 100644
--- a/elf/dl-symaddr.c
+++ b/elf/dl-symaddr.c
@@ -1,5 +1,5 @@
/* Get the symbol address. Generic version.
- Copyright (C) 1999-2014 Free Software Foundation, Inc.
+ Copyright (C) 1999-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
@@ -30,3 +30,4 @@ _dl_symbol_address (struct link_map *map, const ElfW(Sym) *ref)
else
return (void *) value;
}
+rtld_hidden_def (_dl_symbol_address)
diff --git a/elf/dl-sysdep.c b/elf/dl-sysdep.c
index d8cdb7e24b..1cc7ea344d 100644
--- a/elf/dl-sysdep.c
+++ b/elf/dl-sysdep.c
@@ -1,5 +1,5 @@
/* Operating system support for run-time dynamic linker. Generic Unix version.
- Copyright (C) 1995-2014 Free Software Foundation, Inc.
+ Copyright (C) 1995-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
@@ -54,7 +54,7 @@ extern void __libc_check_standard_fds (void);
ElfW(Addr) _dl_base_addr;
#endif
int __libc_enable_secure attribute_relro = 0;
-INTVARDEF(__libc_enable_secure)
+rtld_hidden_data_def (__libc_enable_secure)
int __libc_multiple_libcs = 0; /* Defining this here avoids the inclusion
of init-first. */
/* This variable contains the lowest stack address ever used. */
@@ -108,7 +108,7 @@ _dl_sysdep_start (void **start_argptr,
#endif
__libc_stack_end = DL_STACK_END (start_argptr);
- DL_FIND_ARG_COMPONENTS (start_argptr, _dl_argc, INTUSE(_dl_argv), _environ,
+ DL_FIND_ARG_COMPONENTS (start_argptr, _dl_argc, _dl_argv, _environ,
GLRO(dl_auxv));
user_entry = (ElfW(Addr)) ENTRY_POINT;
@@ -148,7 +148,7 @@ _dl_sysdep_start (void **start_argptr,
#ifndef HAVE_AUX_SECURE
seen = -1;
#endif
- INTUSE(__libc_enable_secure) = av->a_un.a_val;
+ __libc_enable_secure = av->a_un.a_val;
break;
case AT_PLATFORM:
GLRO(dl_platform) = (void *) av->a_un.a_val;
@@ -199,7 +199,7 @@ _dl_sysdep_start (void **start_argptr,
/* If one of the two pairs of IDs does not match this is a setuid
or setgid run. */
- INTUSE(__libc_enable_secure) = uid | gid;
+ __libc_enable_secure = uid | gid;
}
#endif
@@ -243,7 +243,7 @@ _dl_sysdep_start (void **start_argptr,
/* If this is a SUID program we make sure that FDs 0, 1, and 2 are
allocated. If necessary we are doing it ourself. If it is not
possible we stop the program. */
- if (__builtin_expect (INTUSE(__libc_enable_secure), 0))
+ if (__builtin_expect (__libc_enable_secure, 0))
__libc_check_standard_fds ();
(*dl_main) (phdr, phnum, &user_entry, GLRO(dl_auxv));
diff --git a/elf/dl-tls.c b/elf/dl-tls.c
index dbaea0aa91..20c7e33c41 100644
--- a/elf/dl-tls.c
+++ b/elf/dl-tls.c
@@ -1,5 +1,5 @@
/* Thread-local storage handling in the ELF dynamic linker. Generic version.
- Copyright (C) 2002-2014 Free Software Foundation, Inc.
+ Copyright (C) 2002-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
@@ -23,6 +23,7 @@
#include <stdlib.h>
#include <unistd.h>
#include <sys/param.h>
+#include <atomic.h>
#include <tls.h>
#include <dl-tls.h>
@@ -34,14 +35,12 @@
/* Out-of-memory handler. */
-#ifdef SHARED
static void
__attribute__ ((__noreturn__))
oom (void)
{
_dl_fatal_printf ("cannot allocate memory for thread-local data: ABORT\n");
}
-#endif
size_t
@@ -105,6 +104,33 @@ _dl_next_tls_modid (void)
}
+size_t
+internal_function
+_dl_count_modids (void)
+{
+ /* It is rare that we have gaps; see elf/dl-open.c (_dl_open) where
+ we fail to load a module and unload it leaving a gap. If we don't
+ have gaps then the number of modids is the current maximum so
+ return that. */
+ if (__glibc_likely (!GL(dl_tls_dtv_gaps)))
+ return GL(dl_tls_max_dtv_idx);
+
+ /* We have gaps and are forced to count the non-NULL entries. */
+ size_t n = 0;
+ struct dtv_slotinfo_list *runp = GL(dl_tls_dtv_slotinfo_list);
+ while (runp != NULL)
+ {
+ for (size_t i = 0; i < runp->len; ++i)
+ if (runp->slotinfo[i].map != NULL)
+ ++n;
+
+ runp = runp->next;
+ }
+
+ return n;
+}
+
+
#ifdef SHARED
void
internal_function
@@ -370,6 +396,53 @@ _dl_allocate_tls_storage (void)
}
+#ifndef SHARED
+extern dtv_t _dl_static_dtv[];
+# define _dl_initial_dtv (&_dl_static_dtv[1])
+#endif
+
+static dtv_t *
+_dl_resize_dtv (dtv_t *dtv)
+{
+ /* Resize the dtv. */
+ dtv_t *newp;
+ /* Load GL(dl_tls_max_dtv_idx) atomically since it may be written to by
+ other threads concurrently. */
+ size_t newsize
+ = atomic_load_acquire (&GL(dl_tls_max_dtv_idx)) + DTV_SURPLUS;
+ size_t oldsize = dtv[-1].counter;
+
+ if (dtv == GL(dl_initial_dtv))
+ {
+ /* This is the initial dtv that was either statically allocated in
+ __libc_setup_tls or allocated during rtld startup using the
+ dl-minimal.c malloc instead of the real malloc. We can't free
+ it, we have to abandon the old storage. */
+
+ newp = malloc ((2 + newsize) * sizeof (dtv_t));
+ if (newp == NULL)
+ oom ();
+ memcpy (newp, &dtv[-1], (2 + oldsize) * sizeof (dtv_t));
+ }
+ else
+ {
+ newp = realloc (&dtv[-1],
+ (2 + newsize) * sizeof (dtv_t));
+ if (newp == NULL)
+ oom ();
+ }
+
+ newp[0].counter = newsize;
+
+ /* Clear the newly allocated part. */
+ memset (newp + 2 + oldsize, '\0',
+ (newsize - oldsize) * sizeof (dtv_t));
+
+ /* Return the generation counter. */
+ return &newp[1];
+}
+
+
void *
internal_function
_dl_allocate_tls_init (void *result)
@@ -383,6 +456,16 @@ _dl_allocate_tls_init (void *result)
size_t total = 0;
size_t maxgen = 0;
+ /* Check if the current dtv is big enough. */
+ if (dtv[-1].counter < GL(dl_tls_max_dtv_idx))
+ {
+ /* Resize the dtv. */
+ dtv = _dl_resize_dtv (dtv);
+
+ /* Install this new dtv in the thread data structures. */
+ INSTALL_DTV (result, &dtv[-1]);
+ }
+
/* We have to prepare the dtv for all currently loaded modules using
TLS. For those which are dynamically loaded we add the values
indicating deferred allocation. */
@@ -407,19 +490,17 @@ _dl_allocate_tls_init (void *result)
/* Keep track of the maximum generation number. This might
not be the generation counter. */
+ assert (listp->slotinfo[cnt].gen <= GL(dl_tls_generation));
maxgen = MAX (maxgen, listp->slotinfo[cnt].gen);
+ dtv[map->l_tls_modid].pointer.val = TLS_DTV_UNALLOCATED;
+ dtv[map->l_tls_modid].pointer.is_static = false;
+
if (map->l_tls_offset == NO_TLS_OFFSET
|| map->l_tls_offset == FORCED_DYNAMIC_TLS_OFFSET)
- {
- /* For dynamically loaded modules we simply store
- the value indicating deferred allocation. */
- dtv[map->l_tls_modid].pointer.val = TLS_DTV_UNALLOCATED;
- dtv[map->l_tls_modid].pointer.is_static = false;
- continue;
- }
+ continue;
- assert (map->l_tls_modid == cnt);
+ assert (map->l_tls_modid == total + cnt);
assert (map->l_tls_blocksize >= map->l_tls_initimage_size);
#if TLS_TCB_AT_TP
assert ((size_t) map->l_tls_offset >= map->l_tls_blocksize);
@@ -431,8 +512,6 @@ _dl_allocate_tls_init (void *result)
#endif
/* Copy the initialization image and clear the BSS part. */
- dtv[map->l_tls_modid].pointer.val = dest;
- dtv[map->l_tls_modid].pointer.is_static = true;
memset (__mempcpy (dest, map->l_tls_initimage,
map->l_tls_initimage_size), '\0',
map->l_tls_blocksize - map->l_tls_initimage_size);
@@ -464,11 +543,6 @@ _dl_allocate_tls (void *mem)
rtld_hidden_def (_dl_allocate_tls)
-#ifndef SHARED
-extern dtv_t _dl_static_dtv[];
-# define _dl_initial_dtv (&_dl_static_dtv[1])
-#endif
-
void
internal_function
_dl_deallocate_tls (void *tcb, bool dealloc_tcb)
@@ -600,13 +674,16 @@ _dl_update_slotinfo (unsigned long int req_modid)
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 >= total + cnt)
{
- free (dtv[total + cnt].pointer.val);
+ /* 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))
+ free (dtv[total + cnt].pointer.val);
dtv[total + cnt].pointer.val = TLS_DTV_UNALLOCATED;
+ dtv[total + cnt].pointer.is_static = false;
}
continue;
@@ -617,41 +694,10 @@ _dl_update_slotinfo (unsigned long int req_modid)
assert (total + cnt == modid);
if (dtv[-1].counter < modid)
{
- /* Reallocate the dtv. */
- dtv_t *newp;
- size_t newsize = GL(dl_tls_max_dtv_idx) + DTV_SURPLUS;
- size_t oldsize = dtv[-1].counter;
-
- assert (map->l_tls_modid <= newsize);
-
- if (dtv == GL(dl_initial_dtv))
- {
- /* 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
- free it, we have to abandon the old storage. */
-
- newp = malloc ((2 + newsize) * sizeof (dtv_t));
- if (newp == NULL)
- oom ();
- memcpy (newp, &dtv[-1], (2 + oldsize) * sizeof (dtv_t));
- }
- else
- {
- newp = realloc (&dtv[-1],
- (2 + newsize) * sizeof (dtv_t));
- if (newp == NULL)
- oom ();
- }
+ /* Resize the dtv. */
+ dtv = _dl_resize_dtv (dtv);
- newp[0].counter = newsize;
-
- /* Clear the newly allocated part. */
- memset (newp + 2 + oldsize, '\0',
- (newsize - oldsize) * sizeof (dtv_t));
-
- /* Point dtv to the generation counter. */
- dtv = &newp[1];
+ assert (modid <= dtv[-1].counter);
/* Install this new dtv in the thread data
structures. */
@@ -670,10 +716,8 @@ _dl_update_slotinfo (unsigned long int req_modid)
memalign and not malloc. */
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;
+ dtv[modid].pointer.is_static = false;
if (modid == req_modid)
the_map = map;
@@ -711,36 +755,41 @@ tls_get_addr_tail (GET_ADDR_ARGS, dtv_t *dtv, struct link_map *the_map)
the_map = listp->slotinfo[idx].map;
}
- 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))
+ if (__glibc_unlikely (the_map->l_tls_offset
+ != FORCED_DYNAMIC_TLS_OFFSET))
{
__rtld_lock_lock_recursive (GL(dl_load_lock));
- if (__builtin_expect (the_map->l_tls_offset == NO_TLS_OFFSET, 1))
+ if (__glibc_likely (the_map->l_tls_offset == NO_TLS_OFFSET))
{
the_map->l_tls_offset = FORCED_DYNAMIC_TLS_OFFSET;
__rtld_lock_unlock_recursive (GL(dl_load_lock));
}
- else
+ else if (__glibc_likely (the_map->l_tls_offset
+ != FORCED_DYNAMIC_TLS_OFFSET))
{
+#if TLS_TCB_AT_TP
+ void *p = (char *) THREAD_SELF - the_map->l_tls_offset;
+#elif TLS_DTV_AT_TP
+ void *p = (char *) THREAD_SELF + the_map->l_tls_offset + TLS_PRE_TCB_SIZE;
+#else
+# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
+#endif
__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;
- }
+ dtv[GET_ADDR_MODULE].pointer.is_static = true;
+ dtv[GET_ADDR_MODULE].pointer.val = p;
+
+ return (char *) p + GET_ADDR_OFFSET;
}
+ else
+ __rtld_lock_unlock_recursive (GL(dl_load_lock));
}
void *p = dtv[GET_ADDR_MODULE].pointer.val = allocate_and_init (the_map);
- dtv[GET_ADDR_MODULE].pointer.is_static = false;
+ assert (!dtv[GET_ADDR_MODULE].pointer.is_static);
return (char *) p + GET_ADDR_OFFSET;
}
@@ -755,12 +804,22 @@ update_get_addr (GET_ADDR_ARGS)
void *p = dtv[GET_ADDR_MODULE].pointer.val;
- if (__builtin_expect (p == TLS_DTV_UNALLOCATED, 0))
+ if (__glibc_unlikely (p == TLS_DTV_UNALLOCATED))
return tls_get_addr_tail (GET_ADDR_PARAM, dtv, the_map);
return (void *) p + GET_ADDR_OFFSET;
}
+/* For all machines that have a non-macro version of __tls_get_addr, we
+ want to use rtld_hidden_proto/rtld_hidden_def in order to call the
+ internal alias for __tls_get_addr from ld.so. This avoids a PLT entry
+ in ld.so for __tls_get_addr. */
+
+#ifndef __tls_get_addr
+extern void * __tls_get_addr (GET_ADDR_ARGS);
+rtld_hidden_proto (__tls_get_addr)
+rtld_hidden_def (__tls_get_addr)
+#endif
/* The generic dynamic and local dynamic model cannot be used in
statically linked applications. */
@@ -769,12 +828,12 @@ __tls_get_addr (GET_ADDR_ARGS)
{
dtv_t *dtv = THREAD_DTV ();
- if (__builtin_expect (dtv[0].counter != GL(dl_tls_generation), 0))
+ if (__glibc_unlikely (dtv[0].counter != GL(dl_tls_generation)))
return update_get_addr (GET_ADDR_PARAM);
void *p = dtv[GET_ADDR_MODULE].pointer.val;
- if (__builtin_expect (p == TLS_DTV_UNALLOCATED, 0))
+ if (__glibc_unlikely (p == TLS_DTV_UNALLOCATED))
return tls_get_addr_tail (GET_ADDR_PARAM, dtv, NULL);
return (char *) p + GET_ADDR_OFFSET;
@@ -787,12 +846,12 @@ __tls_get_addr (GET_ADDR_ARGS)
void *
_dl_tls_get_addr_soft (struct link_map *l)
{
- if (__builtin_expect (l->l_tls_modid == 0, 0))
+ if (__glibc_unlikely (l->l_tls_modid == 0))
/* This module has no TLS segment. */
return NULL;
dtv_t *dtv = THREAD_DTV ();
- if (__builtin_expect (dtv[0].counter != GL(dl_tls_generation), 0))
+ if (__glibc_unlikely (dtv[0].counter != GL(dl_tls_generation)))
{
/* This thread's DTV is not completely current,
but it might already cover this module. */
@@ -817,7 +876,7 @@ _dl_tls_get_addr_soft (struct link_map *l)
}
void *data = dtv[l->l_tls_modid].pointer.val;
- if (__builtin_expect (data == TLS_DTV_UNALLOCATED, 0))
+ if (__glibc_unlikely (data == TLS_DTV_UNALLOCATED))
/* The DTV is current, but this thread has not yet needed
to allocate this module's segment. */
data = NULL;
diff --git a/elf/dl-tsd.c b/elf/dl-tsd.c
index dfa287011f..e3e4d972b6 100644
--- a/elf/dl-tsd.c
+++ b/elf/dl-tsd.c
@@ -1,5 +1,5 @@
/* Thread-local data used by error handling for runtime dynamic linker.
- Copyright (C) 2002-2014 Free Software Foundation, Inc.
+ Copyright (C) 2002-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
diff --git a/elf/dl-unmap-segments.h b/elf/dl-unmap-segments.h
new file mode 100644
index 0000000000..ae802003ce
--- /dev/null
+++ b/elf/dl-unmap-segments.h
@@ -0,0 +1,35 @@
+/* Unmap a shared object's segments. Generic version.
+ Copyright (C) 2014-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/>. */
+
+#ifndef _DL_UNMAP_SEGMENTS_H
+#define _DL_UNMAP_SEGMENTS_H 1
+
+#include <link.h>
+#include <sys/mman.h>
+
+/* _dl_map_segments ensures that any whole pages in gaps between segments
+ are filled in with PROT_NONE mappings. So we can just unmap the whole
+ range in one fell swoop. */
+
+static __always_inline void
+_dl_unmap_segments (struct link_map *l)
+{
+ __munmap ((void *) l->l_map_start, l->l_map_end - l->l_map_start);
+}
+
+#endif /* dl-unmap-segments.h */
diff --git a/elf/dl-version.c b/elf/dl-version.c
index 651d4cf4ed..f6e5cd9e75 100644
--- a/elf/dl-version.c
+++ b/elf/dl-version.c
@@ -1,5 +1,5 @@
/* Handle symbol and library versioning.
- Copyright (C) 1997-2014 Free Software Foundation, Inc.
+ Copyright (C) 1997-2015 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
@@ -82,13 +82,13 @@ match_symbol (const char *name, Lmid_t ns, ElfW(Word) hash, const char *string,
int result = 0;
/* Display information about what we are doing while debugging. */
- if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_VERSIONS, 0))
+ if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_VERSIONS))
_dl_debug_printf ("\
checking for version `%s' in file %s [%lu] required by file %s [%lu]\n",
string, DSO_FILENAME (map->l_name),
map->l_ns, name, ns);
- if (__builtin_expect (map->l_info[VERSYMIDX (DT_VERDEF)] == NULL, 0))
+ if (__glibc_unlikely (map->l_info[VERSYMIDX (DT_VERDEF)] == NULL))
{
/* The file has no symbol versioning. I.e., the dependent
object was linked against another version of this file. We
@@ -145,7 +145,7 @@ no version information available (required by ", name, ")");
}
/* Symbol not found. If it was a weak reference it is not fatal. */
- if (__builtin_expect (weak, 1))
+ if (__glibc_likely (weak))
{
if (verbose)
{
@@ -291,7 +291,7 @@ _dl_check_map_versions (struct link_map *map, int verbose, int trace_mode)
section. */
map->l_versions = (struct r_found_version *)
calloc (ndx_high + 1, sizeof (*map->l_versions));
- if (__builtin_expect (map->l_versions == NULL, 0))
+ if (__glibc_unlikely (map->l_versions == NULL))
{
errstring = N_("cannot allocate version reference table");
errval = ENOMEM;
@@ -316,7 +316,7 @@ _dl_check_map_versions (struct link_map *map, int verbose, int trace_mode)
{
ElfW(Half) ndx = aux->vna_other & 0x7fff;
/* In trace mode, dependencies may be missing. */
- if (__builtin_expect (ndx < map->l_nversions, 1))
+ if (__glibc_likely (ndx < map->l_nversions))
{
map->l_versions[ndx].hash = aux->vna_hash;
map->l_versions[ndx].hidden = aux->vna_other & 0x8000;
diff --git a/elf/dl-writev.h b/elf/dl-writev.h
index ad67c1d82c..3e6d2f4975 100644
--- a/elf/dl-writev.h
+++ b/elf/dl-writev.h
@@ -1,5 +1,5 @@
/* Message-writing for the dynamic linker. Generic version.
- Copyright (C) 2013-2014 Free Software Foundation, Inc.
+ Copyright (C) 2013-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
@@ -42,7 +42,7 @@ _dl_writev (int fd, const struct iovec *iov, size_t niov)
errno when it's being used by another thread that cares about it.
Yet we must be sure not to try calling the lock functions before
the thread library is fully initialized. */
- if (__builtin_expect (INTUSE (_dl_starting_up), 0))
+ if (__glibc_unlikely (_dl_starting_up))
__writev (fd, iov, niov);
else
{
diff --git a/elf/do-rel.h b/elf/do-rel.h
index a1cbab9fd1..0569b0a163 100644
--- a/elf/do-rel.h
+++ b/elf/do-rel.h
@@ -1,5 +1,5 @@
/* Do relocations for ELF dynamic linking.
- Copyright (C) 1995-2014 Free Software Foundation, Inc.
+ Copyright (C) 1995-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
diff --git a/elf/dynamic-link.h b/elf/dynamic-link.h
index 7b3e29581d..8d428e20d3 100644
--- a/elf/dynamic-link.h
+++ b/elf/dynamic-link.h
@@ -1,5 +1,5 @@
/* Inline functions for dynamic linking.
- Copyright (C) 1995-2014 Free Software Foundation, Inc.
+ Copyright (C) 1995-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
@@ -25,11 +25,14 @@
an attempt to allocate it in surplus space on the fly. If that
can't be done, we fall back to the error that DF_STATIC_TLS is
intended to produce. */
+#define HAVE_STATIC_TLS(map, sym_map) \
+ (__builtin_expect ((sym_map)->l_tls_offset != NO_TLS_OFFSET \
+ && ((sym_map)->l_tls_offset \
+ != FORCED_DYNAMIC_TLS_OFFSET), 1))
+
#define CHECK_STATIC_TLS(map, sym_map) \
do { \
- if (__builtin_expect ((sym_map)->l_tls_offset == NO_TLS_OFFSET \
- || ((sym_map)->l_tls_offset \
- == FORCED_DYNAMIC_TLS_OFFSET), 0)) \
+ if (!HAVE_STATIC_TLS (map, sym_map)) \
_dl_allocate_static_tls (sym_map); \
} while (0)
@@ -122,8 +125,7 @@ elf_machine_lazy_rel (struct link_map *map,
ranges[0].size = (map)->l_info[DT_##RELOC##SZ]->d_un.d_val; \
if (map->l_info[VERSYMIDX (DT_##RELOC##COUNT)] != NULL) \
ranges[0].nrelative \
- = MIN (map->l_info[VERSYMIDX (DT_##RELOC##COUNT)]->d_un.d_val, \
- ranges[0].size / sizeof (ElfW(reloc))); \
+ = map->l_info[VERSYMIDX (DT_##RELOC##COUNT)]->d_un.d_val; \
} \
if ((map)->l_info[DT_PLTREL] \
&& (!test_rel || (map)->l_info[DT_PLTREL]->d_un.d_val == DT_##RELOC)) \
diff --git a/elf/elf.h b/elf/elf.h
index 40e87b21c3..fbadda4377 100644
--- a/elf/elf.h
+++ b/elf/elf.h
@@ -1,5 +1,5 @@
/* This file defines standard ELF types, structures, and macros.
- Copyright (C) 1995-2014 Free Software Foundation, Inc.
+ Copyright (C) 1995-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
@@ -249,6 +249,7 @@ typedef struct
#define EM_OPENRISC 92 /* OpenRISC 32-bit embedded processor */
#define EM_ARC_A5 93 /* ARC Cores Tangent-A5 */
#define EM_XTENSA 94 /* Tensilica Xtensa Architecture */
+#define EM_ALTERA_NIOS2 113 /* Altera Nios II */
#define EM_AARCH64 183 /* ARM AARCH64 */
#define EM_TILEPRO 188 /* Tilera TILEPro */
#define EM_MICROBLAZE 189 /* Xilinx MicroBlaze */
@@ -366,13 +367,38 @@ typedef struct
required */
#define SHF_GROUP (1 << 9) /* Section is member of a group. */
#define SHF_TLS (1 << 10) /* Section hold thread-local data. */
+#define SHF_COMPRESSED (1 << 11) /* Section with compressed data. */
#define SHF_MASKOS 0x0ff00000 /* OS-specific. */
#define SHF_MASKPROC 0xf0000000 /* Processor-specific */
#define SHF_ORDERED (1 << 30) /* Special ordering requirement
(Solaris). */
-#define SHF_EXCLUDE (1 << 31) /* Section is excluded unless
+#define SHF_EXCLUDE (1U << 31) /* Section is excluded unless
referenced or allocated (Solaris).*/
+/* Section compression header. Used when SHF_COMPRESSED is set. */
+
+typedef struct
+{
+ Elf32_Word ch_type; /* Compression format. */
+ Elf32_Word ch_size; /* Uncompressed data size. */
+ Elf32_Word ch_addralign; /* Uncompressed data alignment. */
+} Elf32_Chdr;
+
+typedef struct
+{
+ Elf64_Word ch_type; /* Compression format. */
+ Elf64_Word ch_reserved;
+ Elf64_Xword ch_size; /* Uncompressed data size. */
+ Elf64_Xword ch_addralign; /* Uncompressed data alignment. */
+} Elf64_Chdr;
+
+/* Legal values for ch_type (compression algorithm). */
+#define ELFCOMPRESS_ZLIB 1 /* ZLIB/DEFLATE algorithm. */
+#define ELFCOMPRESS_LOOS 0x60000000 /* Start of OS-specific. */
+#define ELFCOMPRESS_HIOS 0x6fffffff /* End of OS-specific. */
+#define ELFCOMPRESS_LOPROC 0x70000000 /* Start of processor-specific. */
+#define ELFCOMPRESS_HIPROC 0x7fffffff /* End of processor-specific. */
+
/* Section group handling. */
#define GRP_COMDAT 0x1 /* Mark group as COMDAT. */
@@ -1383,6 +1409,7 @@ typedef struct
#define EF_MIPS_64BIT_WHIRL 16
#define EF_MIPS_ABI2 32
#define EF_MIPS_ABI_ON32 64
+#define EF_MIPS_FP64 512 /* Uses FP64 (12 callee-saved). */
#define EF_MIPS_NAN2008 1024 /* Uses IEEE 754-2008 NaN encoding. */
#define EF_MIPS_ARCH 0xf0000000 /* MIPS architecture level. */
@@ -1631,9 +1658,10 @@ typedef struct
/* Legal values for p_type field of Elf32_Phdr. */
-#define PT_MIPS_REGINFO 0x70000000 /* Register usage information */
-#define PT_MIPS_RTPROC 0x70000001 /* Runtime procedure table. */
-#define PT_MIPS_OPTIONS 0x70000002
+#define PT_MIPS_REGINFO 0x70000000 /* Register usage information. */
+#define PT_MIPS_RTPROC 0x70000001 /* Runtime procedure table. */
+#define PT_MIPS_OPTIONS 0x70000002
+#define PT_MIPS_ABIFLAGS 0x70000003 /* FP mode requirement. */
/* Special program header types. */
@@ -1699,7 +1727,11 @@ typedef struct
PLT is writable. For a non-writable PLT, this is omitted or has a zero
value. */
#define DT_MIPS_RWPLT 0x70000034
-#define DT_MIPS_NUM 0x35
+/* An alternative description of the classic MIPS RLD_MAP that is usable
+ in a PIE as it stores a relative offset from the address of the tag
+ rather than an absolute address. */
+#define DT_MIPS_RLD_MAP_REL 0x70000035
+#define DT_MIPS_NUM 0x36
/* Legal values for DT_MIPS_FLAGS Elf32_Dyn entry. */
@@ -1755,6 +1787,101 @@ typedef struct
typedef Elf32_Addr Elf32_Conflict;
+typedef struct
+{
+ /* Version of flags structure. */
+ Elf32_Half version;
+ /* The level of the ISA: 1-5, 32, 64. */
+ unsigned char isa_level;
+ /* The revision of ISA: 0 for MIPS V and below, 1-n otherwise. */
+ unsigned char isa_rev;
+ /* The size of general purpose registers. */
+ unsigned char gpr_size;
+ /* The size of co-processor 1 registers. */
+ unsigned char cpr1_size;
+ /* The size of co-processor 2 registers. */
+ unsigned char cpr2_size;
+ /* The floating-point ABI. */
+ unsigned char fp_abi;
+ /* Processor-specific extension. */
+ Elf32_Word isa_ext;
+ /* Mask of ASEs used. */
+ Elf32_Word ases;
+ /* Mask of general flags. */
+ Elf32_Word flags1;
+ Elf32_Word flags2;
+} Elf_MIPS_ABIFlags_v0;
+
+/* Values for the register size bytes of an abi flags structure. */
+
+#define MIPS_AFL_REG_NONE 0x00 /* No registers. */
+#define MIPS_AFL_REG_32 0x01 /* 32-bit registers. */
+#define MIPS_AFL_REG_64 0x02 /* 64-bit registers. */
+#define MIPS_AFL_REG_128 0x03 /* 128-bit registers. */
+
+/* Masks for the ases word of an ABI flags structure. */
+
+#define MIPS_AFL_ASE_DSP 0x00000001 /* DSP ASE. */
+#define MIPS_AFL_ASE_DSPR2 0x00000002 /* DSP R2 ASE. */
+#define MIPS_AFL_ASE_EVA 0x00000004 /* Enhanced VA Scheme. */
+#define MIPS_AFL_ASE_MCU 0x00000008 /* MCU (MicroController) ASE. */
+#define MIPS_AFL_ASE_MDMX 0x00000010 /* MDMX ASE. */
+#define MIPS_AFL_ASE_MIPS3D 0x00000020 /* MIPS-3D ASE. */
+#define MIPS_AFL_ASE_MT 0x00000040 /* MT ASE. */
+#define MIPS_AFL_ASE_SMARTMIPS 0x00000080 /* SmartMIPS ASE. */
+#define MIPS_AFL_ASE_VIRT 0x00000100 /* VZ ASE. */
+#define MIPS_AFL_ASE_MSA 0x00000200 /* MSA ASE. */
+#define MIPS_AFL_ASE_MIPS16 0x00000400 /* MIPS16 ASE. */
+#define MIPS_AFL_ASE_MICROMIPS 0x00000800 /* MICROMIPS ASE. */
+#define MIPS_AFL_ASE_XPA 0x00001000 /* XPA ASE. */
+#define MIPS_AFL_ASE_MASK 0x00001fff /* All ASEs. */
+
+/* Values for the isa_ext word of an ABI flags structure. */
+
+#define MIPS_AFL_EXT_XLR 1 /* RMI Xlr instruction. */
+#define MIPS_AFL_EXT_OCTEON2 2 /* Cavium Networks Octeon2. */
+#define MIPS_AFL_EXT_OCTEONP 3 /* Cavium Networks OcteonP. */
+#define MIPS_AFL_EXT_LOONGSON_3A 4 /* Loongson 3A. */
+#define MIPS_AFL_EXT_OCTEON 5 /* Cavium Networks Octeon. */
+#define MIPS_AFL_EXT_5900 6 /* MIPS R5900 instruction. */
+#define MIPS_AFL_EXT_4650 7 /* MIPS R4650 instruction. */
+#define MIPS_AFL_EXT_4010 8 /* LSI R4010 instruction. */
+#define MIPS_AFL_EXT_4100 9 /* NEC VR4100 instruction. */
+#define MIPS_AFL_EXT_3900 10 /* Toshiba R3900 instruction. */
+#define MIPS_AFL_EXT_10000 11 /* MIPS R10000 instruction. */
+#define MIPS_AFL_EXT_SB1 12 /* Broadcom SB-1 instruction. */
+#define MIPS_AFL_EXT_4111 13 /* NEC VR4111/VR4181 instruction. */
+#define MIPS_AFL_EXT_4120 14 /* NEC VR4120 instruction. */
+#define MIPS_AFL_EXT_5400 15 /* NEC VR5400 instruction. */
+#define MIPS_AFL_EXT_5500 16 /* NEC VR5500 instruction. */
+#define MIPS_AFL_EXT_LOONGSON_2E 17 /* ST Microelectronics Loongson 2E. */
+#define MIPS_AFL_EXT_LOONGSON_2F 18 /* ST Microelectronics Loongson 2F. */
+
+/* Masks for the flags1 word of an ABI flags structure. */
+#define MIPS_AFL_FLAGS1_ODDSPREG 1 /* Uses odd single-precision registers. */
+
+/* Object attribute values. */
+enum
+{
+ /* Not tagged or not using any ABIs affected by the differences. */
+ Val_GNU_MIPS_ABI_FP_ANY = 0,
+ /* Using hard-float -mdouble-float. */
+ Val_GNU_MIPS_ABI_FP_DOUBLE = 1,
+ /* Using hard-float -msingle-float. */
+ Val_GNU_MIPS_ABI_FP_SINGLE = 2,
+ /* Using soft-float. */
+ Val_GNU_MIPS_ABI_FP_SOFT = 3,
+ /* Using -mips32r2 -mfp64. */
+ Val_GNU_MIPS_ABI_FP_OLD_64 = 4,
+ /* Using -mfpxx. */
+ Val_GNU_MIPS_ABI_FP_XX = 5,
+ /* Using -mips32r2 -mfp64. */
+ Val_GNU_MIPS_ABI_FP_64 = 6,
+ /* Using -mips32r2 -mfp64 -mno-odd-spreg. */
+ Val_GNU_MIPS_ABI_FP_64A = 7,
+ /* Maximum allocated FP ABI value. */
+ Val_GNU_MIPS_ABI_FP_MAX = 7
+};
/* HPPA specific definitions. */
@@ -2096,6 +2223,8 @@ typedef Elf32_Addr Elf32_Conflict;
#define R_PPC_GOT_DTPREL16_LO 92 /* half16* (sym+add)@got@dtprel@l */
#define R_PPC_GOT_DTPREL16_HI 93 /* half16* (sym+add)@got@dtprel@h */
#define R_PPC_GOT_DTPREL16_HA 94 /* half16* (sym+add)@got@dtprel@ha */
+#define R_PPC_TLSGD 95 /* none (sym+add)@tlsgd */
+#define R_PPC_TLSLD 96 /* none (sym+add)@tlsld */
/* The remaining relocs are from the Embedded ELF ABI, and are not
in the SVR4 ELF ABI. */
@@ -2139,7 +2268,11 @@ typedef Elf32_Addr Elf32_Conflict;
/* PowerPC specific values for the Dyn d_tag field. */
#define DT_PPC_GOT (DT_LOPROC + 0)
-#define DT_PPC_NUM 1
+#define DT_PPC_OPT (DT_LOPROC + 1)
+#define DT_PPC_NUM 2
+
+/* PowerPC specific values for the DT_PPC_OPT Dyn entry. */
+#define PPC_OPT_TLS 1
/* PowerPC64 relocations defined by the ABIs */
#define R_PPC64_NONE R_PPC_NONE
@@ -2283,7 +2416,7 @@ 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)
-#define DT_PPC64_NUM 3
+#define DT_PPC64_NUM 4
/* PowerPC64 specific values for the DT_PPC64_OPT Dyn entry. */
#define PPC64_OPT_TLS 1
@@ -2362,6 +2495,20 @@ typedef Elf32_Addr Elf32_Conflict;
/* AArch64 relocs. */
#define R_AARCH64_NONE 0 /* No relocation. */
+
+/* ILP32 AArch64 relocs. */
+#define R_AARCH64_P32_ABS32 1 /* Direct 32 bit. */
+#define R_AARCH64_P32_COPY 180 /* Copy symbol at runtime. */
+#define R_AARCH64_P32_GLOB_DAT 181 /* Create GOT entry. */
+#define R_AARCH64_P32_JUMP_SLOT 182 /* Create PLT entry. */
+#define R_AARCH64_P32_RELATIVE 183 /* Adjust by program base. */
+#define R_AARCH64_P32_TLS_DTPMOD 184 /* Module number, 32 bit. */
+#define R_AARCH64_P32_TLS_DTPREL 185 /* Module-relative offset, 32 bit. */
+#define R_AARCH64_P32_TLS_TPREL 186 /* TP-relative offset, 32 bit. */
+#define R_AARCH64_P32_TLSDESC 187 /* TLS Descriptor. */
+#define R_AARCH64_P32_IRELATIVE 188 /* STT_GNU_IFUNC relocation. */
+
+/* LP64 AArch64 relocs. */
#define R_AARCH64_ABS64 257 /* Direct 64 bit. */
#define R_AARCH64_ABS32 258 /* Direct 32 bit. */
#define R_AARCH64_ABS16 259 /* Direct 16-bit. */
@@ -2479,9 +2626,9 @@ typedef Elf32_Addr Elf32_Conflict;
#define R_AARCH64_GLOB_DAT 1025 /* Create GOT entry. */
#define R_AARCH64_JUMP_SLOT 1026 /* Create PLT entry. */
#define R_AARCH64_RELATIVE 1027 /* Adjust by program base. */
-#define R_AARCH64_TLS_DTPMOD64 1028 /* Module number, 64 bit. */
-#define R_AARCH64_TLS_DTPREL64 1029 /* Module-relative offset, 64 bit. */
-#define R_AARCH64_TLS_TPREL64 1030 /* TP-relative offset, 64 bit. */
+#define R_AARCH64_TLS_DTPMOD 1028 /* Module number, 64 bit. */
+#define R_AARCH64_TLS_DTPREL 1029 /* Module-relative offset, 64 bit. */
+#define R_AARCH64_TLS_TPREL 1030 /* TP-relative offset, 64 bit. */
#define R_AARCH64_TLSDESC 1031 /* TLS Descriptor. */
#define R_AARCH64_IRELATIVE 1032 /* STT_GNU_IFUNC relocation. */
@@ -3132,6 +3279,58 @@ typedef Elf32_Addr Elf32_Conflict;
#define R_MICROBLAZE_TLSGOTTPREL32 28 /* TLS Offset From Thread Pointer. */
#define R_MICROBLAZE_TLSTPREL32 29 /* TLS Offset From Thread Pointer. */
+/* Legal values for d_tag (dynamic entry type). */
+#define DT_NIOS2_GP 0x70000002 /* Address of _gp. */
+
+/* Nios II relocations. */
+#define R_NIOS2_NONE 0 /* No reloc. */
+#define R_NIOS2_S16 1 /* Direct signed 16 bit. */
+#define R_NIOS2_U16 2 /* Direct unsigned 16 bit. */
+#define R_NIOS2_PCREL16 3 /* PC relative 16 bit. */
+#define R_NIOS2_CALL26 4 /* Direct call. */
+#define R_NIOS2_IMM5 5 /* 5 bit constant expression. */
+#define R_NIOS2_CACHE_OPX 6 /* 5 bit expression, shift 22. */
+#define R_NIOS2_IMM6 7 /* 6 bit constant expression. */
+#define R_NIOS2_IMM8 8 /* 8 bit constant expression. */
+#define R_NIOS2_HI16 9 /* High 16 bit. */
+#define R_NIOS2_LO16 10 /* Low 16 bit. */
+#define R_NIOS2_HIADJ16 11 /* High 16 bit, adjusted. */
+#define R_NIOS2_BFD_RELOC_32 12 /* 32 bit symbol value + addend. */
+#define R_NIOS2_BFD_RELOC_16 13 /* 16 bit symbol value + addend. */
+#define R_NIOS2_BFD_RELOC_8 14 /* 8 bit symbol value + addend. */
+#define R_NIOS2_GPREL 15 /* 16 bit GP pointer offset. */
+#define R_NIOS2_GNU_VTINHERIT 16 /* GNU C++ vtable hierarchy. */
+#define R_NIOS2_GNU_VTENTRY 17 /* GNU C++ vtable member usage. */
+#define R_NIOS2_UJMP 18 /* Unconditional branch. */
+#define R_NIOS2_CJMP 19 /* Conditional branch. */
+#define R_NIOS2_CALLR 20 /* Indirect call through register. */
+#define R_NIOS2_ALIGN 21 /* Alignment requirement for
+ linker relaxation. */
+#define R_NIOS2_GOT16 22 /* 16 bit GOT entry. */
+#define R_NIOS2_CALL16 23 /* 16 bit GOT entry for function. */
+#define R_NIOS2_GOTOFF_LO 24 /* %lo of offset to GOT pointer. */
+#define R_NIOS2_GOTOFF_HA 25 /* %hiadj of offset to GOT pointer. */
+#define R_NIOS2_PCREL_LO 26 /* %lo of PC relative offset. */
+#define R_NIOS2_PCREL_HA 27 /* %hiadj of PC relative offset. */
+#define R_NIOS2_TLS_GD16 28 /* 16 bit GOT offset for TLS GD. */
+#define R_NIOS2_TLS_LDM16 29 /* 16 bit GOT offset for TLS LDM. */
+#define R_NIOS2_TLS_LDO16 30 /* 16 bit module relative offset. */
+#define R_NIOS2_TLS_IE16 31 /* 16 bit GOT offset for TLS IE. */
+#define R_NIOS2_TLS_LE16 32 /* 16 bit LE TP-relative offset. */
+#define R_NIOS2_TLS_DTPMOD 33 /* Module number. */
+#define R_NIOS2_TLS_DTPREL 34 /* Module-relative offset. */
+#define R_NIOS2_TLS_TPREL 35 /* TP-relative offset. */
+#define R_NIOS2_COPY 36 /* Copy symbol at runtime. */
+#define R_NIOS2_GLOB_DAT 37 /* Create GOT entry. */
+#define R_NIOS2_JUMP_SLOT 38 /* Create PLT entry. */
+#define R_NIOS2_RELATIVE 39 /* Adjust by program base. */
+#define R_NIOS2_GOTOFF 40 /* 16 bit offset to GOT pointer. */
+#define R_NIOS2_CALL26_NOAT 41 /* Direct call in .noat section. */
+#define R_NIOS2_GOT_LO 42 /* %lo() of GOT entry. */
+#define R_NIOS2_GOT_HA 43 /* %hiadj() of GOT entry. */
+#define R_NIOS2_CALL_LO 44 /* %lo() of function GOT entry. */
+#define R_NIOS2_CALL_HA 45 /* %hiadj() of function GOT entry. */
+
/* TILEPro relocations. */
#define R_TILEPRO_NONE 0 /* No reloc */
#define R_TILEPRO_32 1 /* Direct 32 bit */
diff --git a/elf/enbl-secure.c b/elf/enbl-secure.c
index c09a5f7917..7d04ffb93e 100644
--- a/elf/enbl-secure.c
+++ b/elf/enbl-secure.c
@@ -1,5 +1,5 @@
/* Define and initialize the `__libc_enable_secure' flag. Generic version.
- Copyright (C) 1996-2014 Free Software Foundation, Inc.
+ Copyright (C) 1996-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
diff --git a/elf/get-dynamic-info.h b/elf/get-dynamic-info.h
index 20ccf30b2a..dc8359d36a 100644
--- a/elf/get-dynamic-info.h
+++ b/elf/get-dynamic-info.h
@@ -1,5 +1,5 @@
/* Read the dynamic section at DYN and fill in INFO with indices DT_*.
- Copyright (C) 2012-2014 Free Software Foundation, Inc.
+ Copyright (C) 2012-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
@@ -17,6 +17,7 @@
<http://www.gnu.org/licenses/>. */
#include <assert.h>
+#include <libc-internal.h>
#ifndef RESOLVE_MAP
static
@@ -47,7 +48,15 @@ elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp)
info[dyn->d_tag] = dyn;
else if (dyn->d_tag >= DT_LOPROC &&
dyn->d_tag < DT_LOPROC + DT_THISPROCNUM)
- info[dyn->d_tag - DT_LOPROC + DT_NUM] = dyn;
+ {
+ /* This does not violate the array bounds of l->l_info, but
+ gcc 4.6 on sparc somehow does not see this. */
+ DIAG_PUSH_NEEDS_COMMENT;
+ DIAG_IGNORE_NEEDS_COMMENT (4.6,
+ "-Warray-bounds");
+ info[dyn->d_tag - DT_LOPROC + DT_NUM] = dyn;
+ DIAG_POP_NEEDS_COMMENT;
+ }
else if ((d_tag_utype) DT_VERSIONTAGIDX (dyn->d_tag) < DT_VERSIONTAGNUM)
info[VERSYMIDX (dyn->d_tag)] = dyn;
else if ((d_tag_utype) DT_EXTRATAGIDX (dyn->d_tag) < DT_EXTRANUM)
diff --git a/elf/ifuncdep2.c b/elf/ifuncdep2.c
index 99d19263ae..6e66d318a6 100644
--- a/elf/ifuncdep2.c
+++ b/elf/ifuncdep2.c
@@ -2,7 +2,13 @@
#include "ifunc-sel.h"
-int global __attribute__ ((visibility ("protected"))) = -1;
+int global = -1;
+/* Can't use __attribute__((visibility("protected"))) until the GCC bug:
+
+ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65248
+
+ is fixed. */
+asm (".protected global");
static int
one (void)
diff --git a/elf/ifuncmod1.c b/elf/ifuncmod1.c
index 2b8195ce55..0b6138056d 100644
--- a/elf/ifuncmod1.c
+++ b/elf/ifuncmod1.c
@@ -6,7 +6,13 @@
*/
#include "ifunc-sel.h"
-int global __attribute__ ((visibility ("protected"))) = -1;
+int global = -1;
+/* Can't use __attribute__((visibility("protected"))) until the GCC bug:
+
+ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65248
+
+ is fixed. */
+asm (".protected global");
static int
one (void)
diff --git a/elf/ifuncmod5.c b/elf/ifuncmod5.c
index 9a08e8cf53..0e65a63691 100644
--- a/elf/ifuncmod5.c
+++ b/elf/ifuncmod5.c
@@ -1,7 +1,13 @@
/* Test STT_GNU_IFUNC symbols without direct function call. */
#include "ifunc-sel.h"
-int global __attribute__ ((visibility ("protected"))) = -1;
+int global = -1;
+/* Can't use __attribute__((visibility("protected"))) until the GCC bug:
+
+ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65248
+
+ is fixed. */
+asm (".protected global");
static int
one (void)
diff --git a/elf/interp.c b/elf/interp.c
index 49c92f59dc..422ea95e9d 100644
--- a/elf/interp.c
+++ b/elf/interp.c
@@ -1,5 +1,5 @@
/* interp - add information about dynamic loader to shared library objects.
- Copyright (C) 1996-2014 Free Software Foundation, Inc.
+ Copyright (C) 1996-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
@@ -16,5 +16,7 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
+#include <runtime-linker.h>
+
const char __invoke_dynamic_linker__[] __attribute__ ((section (".interp")))
= RUNTIME_LINKER;
diff --git a/elf/ldconfig.c b/elf/ldconfig.c
index 46d295064f..f54ec22d24 100644
--- a/elf/ldconfig.c
+++ b/elf/ldconfig.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1999-2014 Free Software Foundation, Inc.
+/* Copyright (C) 1999-2015 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Andreas Jaeger <aj@suse.de>, 1999.
@@ -324,7 +324,7 @@ print_version (FILE *stream, struct argp_state *state)
Copyright (C) %s Free Software Foundation, Inc.\n\
This is free software; see the source for copying conditions. There is NO\n\
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
-"), "2014");
+"), "2015");
fprintf (stream, gettext ("Written by %s.\n"),
"Andreas Jaeger");
}
@@ -770,7 +770,7 @@ search_dir (const struct dir_entry *entry)
lstat_buf.st_mode = DTTOIF (direntry->d_type);
else
#endif
- if (__builtin_expect (lstat64 (real_file_name, &lstat_buf), 0))
+ if (__glibc_unlikely (lstat64 (real_file_name, &lstat_buf)))
{
error (0, errno, _("Cannot lstat %s"), file_name);
continue;
@@ -794,7 +794,7 @@ search_dir (const struct dir_entry *entry)
continue;
}
}
- if (__builtin_expect (stat64 (target_name, &stat_buf), 0))
+ if (__glibc_unlikely (stat64 (target_name, &stat_buf)))
{
if (opt_verbose)
error (0, errno, _("Cannot stat %s"), file_name);
@@ -893,8 +893,30 @@ search_dir (const struct dir_entry *entry)
/* A link may just point to itself. */
if (is_link)
{
- /* If the path the link points to isn't its soname and it is not
- .so symlink for ld(1) only, we treat it as a normal file. */
+ /* If the path the link points to isn't its soname or it is not
+ the .so symlink for ld(1), we treat it as a normal file.
+
+ You should always do this:
+
+ libfoo.so -> SONAME -> Arbitrary package-chosen name.
+
+ e.g. libfoo.so -> libfoo.so.1 -> libfooimp.so.9.99.
+ Given a SONAME of libfoo.so.1.
+
+ You should *never* do this:
+
+ libfoo.so -> libfooimp.so.9.99
+
+ If you do, and your SONAME is libfoo.so.1, then libfoo.so
+ fails to point at the SONAME. In that case ldconfig may consider
+ libfoo.so as another implementation of SONAME and will create
+ symlinks against it causing problems when you try to upgrade
+ or downgrade. The problems will arise because ldconfig will,
+ depending on directory ordering, creat symlinks against libfoo.so
+ e.g. libfoo.so.1.2 -> libfoo.so, but when libfoo.so is removed
+ (typically by the removal of a development pacakge not required
+ for the runtime) it will break the libfoo.so.1.2 symlink and the
+ application will fail to start. */
const char *real_base_name = basename (real_file_name);
if (strcmp (real_base_name, soname) != 0)
diff --git a/elf/ldd.bash.in b/elf/ldd.bash.in
index 4ff140d302..7fb6c157a0 100644
--- a/elf/ldd.bash.in
+++ b/elf/ldd.bash.in
@@ -1,5 +1,5 @@
#! @BASH@
-# Copyright (C) 1996-2014 Free Software Foundation, Inc.
+# Copyright (C) 1996-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
@@ -38,7 +38,7 @@ while test $# -gt 0; do
printf $"Copyright (C) %s Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-" "2014"
+" "2015"
printf $"Written by %s and %s.
" "Roland McGrath" "Ulrich Drepper"
exit 0
diff --git a/elf/link.h b/elf/link.h
index d5905d1ccb..eaca8028e4 100644
--- a/elf/link.h
+++ b/elf/link.h
@@ -1,6 +1,6 @@
/* Data structure for communication from the run-time dynamic linker for
loaded ELF shared objects.
- Copyright (C) 1995-2014 Free Software Foundation, Inc.
+ Copyright (C) 1995-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
diff --git a/elf/pldd-xx.c b/elf/pldd-xx.c
index e7d87c88d4..2f1962883c 100644
--- a/elf/pldd-xx.c
+++ b/elf/pldd-xx.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2011-2014 Free Software Foundation, Inc.
+/* Copyright (C) 2011-2015 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@gmail.com>, 2011.
@@ -186,35 +186,43 @@ E(find_maps) (pid_t pid, void *auxv, size_t auxv_size)
printf ("%lu:\t%s\n", (unsigned long int) pid, exe);
/* Iterate over the list of objects and print the information. */
- size_t strsize = 256;
- char *str = alloca (strsize);
+ struct scratch_buffer tmpbuf;
+ scratch_buffer_init (&tmpbuf);
+ int status = 0;
do
{
struct E(link_map) m;
if (pread64 (memfd, &m, sizeof (m), list) != sizeof (m))
{
error (0, 0, gettext ("cannot read link map"));
- return EXIT_FAILURE;
+ status = EXIT_FAILURE;
+ goto out;
}
EW(Addr) name_offset = m.l_name;
again:
while (1)
{
- ssize_t n = pread64 (memfd, str, strsize, name_offset);
+ ssize_t n = pread64 (memfd, tmpbuf.data, tmpbuf.length, name_offset);
if (n == -1)
{
error (0, 0, gettext ("cannot read object name"));
- return EXIT_FAILURE;
+ status = EXIT_FAILURE;
+ goto out;
}
- if (memchr (str, '\0', n) != NULL)
+ if (memchr (tmpbuf.data, '\0', n) != NULL)
break;
- str = extend_alloca (str, strsize, strsize * 2);
+ if (!scratch_buffer_grow (&tmpbuf))
+ {
+ error (0, 0, gettext ("cannot allocate buffer for object name"));
+ status = EXIT_FAILURE;
+ goto out;
+ }
}
- if (str[0] == '\0' && name_offset == m.l_name
+ if (((char *)tmpbuf.data)[0] == '\0' && name_offset == m.l_name
&& m.l_libname != 0)
{
/* Try the l_libname element. */
@@ -227,14 +235,16 @@ E(find_maps) (pid_t pid, void *auxv, size_t auxv_size)
}
/* Skip over the executable. */
- if (str[0] != '\0')
- printf ("%s\n", str);
+ if (((char *)tmpbuf.data)[0] != '\0')
+ printf ("%s\n", (char *)tmpbuf.data);
list = m.l_next;
}
while (list != 0);
- return 0;
+ out:
+ scratch_buffer_free (&tmpbuf);
+ return status;
}
diff --git a/elf/pldd.c b/elf/pldd.c
index 684aff4dba..2b862248a6 100644
--- a/elf/pldd.c
+++ b/elf/pldd.c
@@ -1,5 +1,5 @@
/* List dynamic shared objects linked into given process.
- Copyright (C) 2011-2014 Free Software Foundation, Inc.
+ Copyright (C) 2011-2015 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@gmail.com>, 2011.
@@ -34,6 +34,8 @@
#include <unistd.h>
#include <sys/ptrace.h>
#include <sys/stat.h>
+#include <sys/wait.h>
+#include <scratch_buffer.h>
#include <ldsodefs.h>
#include <version.h>
@@ -82,6 +84,7 @@ static char *exe;
/* Local functions. */
static int get_process_info (int dfd, long int pid);
+static void wait_for_ptrace_stop (long int pid);
int
@@ -116,18 +119,25 @@ main (int argc, char *argv[])
if (dfd == -1)
error (EXIT_FAILURE, errno, gettext ("cannot open %s"), buf);
- size_t exesize = 1024;
-#ifdef PATH_MAX
- exesize = PATH_MAX;
-#endif
- exe = alloca (exesize);
+ struct scratch_buffer exebuf;
+ scratch_buffer_init (&exebuf);
ssize_t nexe;
- while ((nexe = readlinkat (dfd, "exe", exe, exesize)) == exesize)
- extend_alloca (exe, exesize, 2 * exesize);
+ while ((nexe = readlinkat (dfd, "exe",
+ exebuf.data, exebuf.length)) == exebuf.length)
+ {
+ if (!scratch_buffer_grow (&exebuf))
+ {
+ nexe = -1;
+ break;
+ }
+ }
if (nexe == -1)
exe = (char *) "<program name undetermined>";
else
- exe[nexe] = '\0';
+ {
+ exe = exebuf.data;
+ exe[nexe] = '\0';
+ }
/* Stop all threads since otherwise the list of loaded modules might
change while we are reading it. */
@@ -170,6 +180,8 @@ main (int argc, char *argv[])
tid);
}
+ wait_for_ptrace_stop (tid);
+
struct thread_list *newp = alloca (sizeof (*newp));
newp->tid = tid;
newp->next = thread_list;
@@ -194,6 +206,27 @@ main (int argc, char *argv[])
}
+/* Wait for PID to enter ptrace-stop state after being attached. */
+static void
+wait_for_ptrace_stop (long int pid)
+{
+ int status;
+
+ /* While waiting for SIGSTOP being delivered to the tracee we have to
+ reinject any other pending signal. Ignore all other errors. */
+ while (waitpid (pid, &status, __WALL) == pid && WIFSTOPPED (status))
+ {
+ /* The STOP signal should not be delivered to the tracee. */
+ if (WSTOPSIG (status) == SIGSTOP)
+ return;
+ if (ptrace (PTRACE_CONT, pid, NULL,
+ (void *) (uintptr_t) WSTOPSIG (status)))
+ /* The only possible error is that the process died. */
+ return;
+ }
+}
+
+
/* Handle program arguments. */
static error_t
parse_opt (int key, char *arg, struct argp_state *state)
@@ -236,7 +269,7 @@ print_version (FILE *stream, struct argp_state *state)
Copyright (C) %s Free Software Foundation, Inc.\n\
This is free software; see the source for copying conditions. There is NO\n\
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
-"), "2014");
+"), "2015");
fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
}
diff --git a/elf/readelflib.c b/elf/readelflib.c
index 94fdc684ff..89e4ce9492 100644
--- a/elf/readelflib.c
+++ b/elf/readelflib.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1999-2014 Free Software Foundation, Inc.
+/* Copyright (C) 1999-2015 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Andreas Jaeger <aj@suse.de>, 1999 and
Jakub Jelinek <jakub@redhat.com>, 1999.
diff --git a/elf/readlib.c b/elf/readlib.c
index 386ebe3c1e..7fd5b8afbf 100644
--- a/elf/readlib.c
+++ b/elf/readlib.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1999-2014 Free Software Foundation, Inc.
+/* Copyright (C) 1999-2015 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Andreas Jaeger <aj@suse.de>, 1999 and
Jakub Jelinek <jakub@redhat.com>, 1999.
@@ -63,6 +63,13 @@ static struct known_names known_libs[] =
};
+/* Check if string corresponds to a GDB Python file. */
+static bool
+is_gdb_python_file (const char *name)
+{
+ size_t len = strlen (name);
+ return len > 7 && strcmp (name + len - 7, "-gdb.py") == 0;
+}
/* Returns 0 if everything is ok, != 0 in case of error. */
int
@@ -157,7 +164,8 @@ process_file (const char *real_file_name, const char *file_name,
beginning of the file. */
size_t len = MIN (statbuf.st_size, 512);
if (memmem (file_contents, len, "GROUP", 5) == NULL
- && memmem (file_contents, len, "GNU ld script", 13) == NULL)
+ && memmem (file_contents, len, "GNU ld script", 13) == NULL
+ && !is_gdb_python_file (file_name))
error (0, 0, _("%s is not an ELF file - it has the wrong magic bytes at the start.\n"),
file_name);
ret = 1;
diff --git a/elf/rtld-Rules b/elf/rtld-Rules
index 0a5d6afade..7433fdfcde 100644
--- a/elf/rtld-Rules
+++ b/elf/rtld-Rules
@@ -1,6 +1,6 @@
# Subroutine makefile for compiling libc modules linked into dynamic linker.
-# Copyright (C) 2002-2014 Free Software Foundation, Inc.
+# Copyright (C) 2002-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
@@ -139,6 +139,9 @@ ifdef rtld-depfiles
endif
# This here is the whole point of all the shenanigans.
-rtld-CPPFLAGS := -DNOT_IN_libc=1 -DIS_IN_rtld=1 -DIN_LIB=rtld
+# Set libof-* for each routine.
+cpp-srcs-left := $(rtld-modules:%.os=%)
+lib := rtld
+include $(patsubst %,$(..)cppflags-iterator.mk,$(cpp-srcs-left))
endif
diff --git a/elf/rtld.c b/elf/rtld.c
index 73ef324ca0..8d0ca3fe24 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -1,5 +1,5 @@
/* Run time dynamic linker.
- Copyright (C) 1995-2014 Free Software Foundation, Inc.
+ Copyright (C) 1995-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
@@ -83,7 +83,7 @@ int _dl_argc attribute_relro attribute_hidden;
char **_dl_argv attribute_relro = NULL;
unsigned int _dl_skip_args attribute_relro attribute_hidden;
#endif
-INTDEF(_dl_argv)
+rtld_hidden_data_def (_dl_argv)
#ifndef THREAD_SET_STACK_GUARD
/* Only exported for architectures that don't store the stack guard canary
@@ -116,7 +116,7 @@ static struct audit_list
and will be since that dynamic linker's _dl_start and dl_main will
never be called. */
int _dl_starting_up = 0;
-INTVARDEF(_dl_starting_up)
+rtld_hidden_def (_dl_starting_up)
#endif
/* This is the structure which defines all variables global to ld.so
@@ -170,7 +170,7 @@ struct rtld_global_ro _rtld_global_ro attribute_relro =
._dl_debug_printf = _dl_debug_printf,
._dl_catch_error = _dl_catch_error,
._dl_signal_error = _dl_signal_error,
- ._dl_mcount = _dl_mcount_internal,
+ ._dl_mcount = _dl_mcount,
._dl_lookup_symbol_x = _dl_lookup_symbol_x,
._dl_check_caller = _dl_check_caller,
._dl_open = _dl_open,
@@ -195,12 +195,6 @@ static void dl_main (const ElfW(Phdr) *phdr, ElfW(Word) phnum,
static struct libname_list _dl_rtld_libname;
static struct libname_list _dl_rtld_libname2;
-/* We expect less than a second for relocation. */
-#ifdef HP_SMALL_TIMING_AVAIL
-# undef HP_TIMING_AVAIL
-# define HP_TIMING_AVAIL HP_SMALL_TIMING_AVAIL
-#endif
-
/* Variable for statistics. */
#ifndef HP_TIMING_NONAVAIL
static hp_timing_t relocate_time;
@@ -270,7 +264,7 @@ _dl_start_final (void *arg, struct dl_start_final_info *info)
{
ElfW(Addr) start_addr;
- if (HP_TIMING_AVAIL)
+ if (HP_SMALL_TIMING_AVAIL)
{
/* If it hasn't happen yet record the startup time. */
if (! HP_TIMING_INLINE)
@@ -279,9 +273,6 @@ _dl_start_final (void *arg, struct dl_start_final_info *info)
else
start_time = info->start_time;
#endif
-
- /* Initialize the timing functions. */
- HP_TIMING_DIFF_INIT ();
}
/* Transfer data about ourselves to the permanent link_map structure. */
@@ -300,26 +291,12 @@ _dl_start_final (void *arg, struct dl_start_final_info *info)
GL(dl_rtld_map).l_text_end = (ElfW(Addr)) _etext;
/* Copy the TLS related data if necessary. */
#ifndef DONT_USE_BOOTSTRAP_MAP
-# if USE___THREAD
- assert (info->l.l_tls_modid != 0);
- GL(dl_rtld_map).l_tls_blocksize = info->l.l_tls_blocksize;
- GL(dl_rtld_map).l_tls_align = info->l.l_tls_align;
- GL(dl_rtld_map).l_tls_firstbyte_offset = info->l.l_tls_firstbyte_offset;
- GL(dl_rtld_map).l_tls_initimage_size = info->l.l_tls_initimage_size;
- GL(dl_rtld_map).l_tls_initimage = info->l.l_tls_initimage;
- GL(dl_rtld_map).l_tls_offset = info->l.l_tls_offset;
- GL(dl_rtld_map).l_tls_modid = 1;
-# else
-# if NO_TLS_OFFSET != 0
+# if NO_TLS_OFFSET != 0
GL(dl_rtld_map).l_tls_offset = NO_TLS_OFFSET;
-# endif
# endif
-
#endif
-#if HP_TIMING_AVAIL
HP_TIMING_NOW (GL(dl_cpuclock_offset));
-#endif
/* Initialize the stack end variable. */
__libc_stack_end = __builtin_frame_address (0);
@@ -332,7 +309,7 @@ _dl_start_final (void *arg, struct dl_start_final_info *info)
#ifndef HP_TIMING_NONAVAIL
hp_timing_t rtld_total_time;
- if (HP_TIMING_AVAIL)
+ if (HP_SMALL_TIMING_AVAIL)
{
hp_timing_t end_time;
@@ -344,7 +321,7 @@ _dl_start_final (void *arg, struct dl_start_final_info *info)
}
#endif
- if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_STATISTICS, 0))
+ if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_STATISTICS))
{
#ifndef HP_TIMING_NONAVAIL
print_statistics (&rtld_total_time);
@@ -374,7 +351,7 @@ _dl_start (void *arg)
#define RESOLVE_MAP(sym, version, flags) (&bootstrap_map)
#include "dynamic-link.h"
- if (HP_TIMING_INLINE && HP_TIMING_AVAIL)
+ if (HP_TIMING_INLINE && HP_SMALL_TIMING_AVAIL)
#ifdef DONT_USE_BOOTSTRAP_MAP
HP_TIMING_NOW (start_time);
#else
@@ -396,9 +373,6 @@ _dl_start (void *arg)
++cnt)
bootstrap_map.l_info[cnt] = 0;
# endif
-# if USE___THREAD
- bootstrap_map.l_tls_modid = 0;
-# endif
#endif
/* Figure out the run-time load address of the dynamic linker itself. */
@@ -412,123 +386,6 @@ _dl_start (void *arg)
bootstrap_map.l_tls_offset = NO_TLS_OFFSET;
#endif
- /* Get the dynamic linker's own program header. First we need the ELF
- file header. The `_begin' symbol created by the linker script points
- to it. When we have something like GOTOFF relocs, we can use a plain
- reference to find the runtime address. Without that, we have to rely
- on the `l_addr' value, which is not the value we want when prelinked. */
-#if USE___THREAD
- dtv_t initdtv[3];
- ElfW(Ehdr) *ehdr
-# ifdef DONT_USE_BOOTSTRAP_MAP
- = (ElfW(Ehdr) *) &_begin;
-# else
-# error This will not work with prelink.
- = (ElfW(Ehdr) *) bootstrap_map.l_addr;
-# endif
- ElfW(Phdr) *phdr = (ElfW(Phdr) *) ((void *) ehdr + ehdr->e_phoff);
- size_t cnt = ehdr->e_phnum; /* PT_TLS is usually the last phdr. */
- while (cnt-- > 0)
- if (phdr[cnt].p_type == PT_TLS)
- {
- void *tlsblock;
- size_t max_align = MAX (TLS_INIT_TCB_ALIGN, phdr[cnt].p_align);
- char *p;
-
- bootstrap_map.l_tls_blocksize = phdr[cnt].p_memsz;
- bootstrap_map.l_tls_align = phdr[cnt].p_align;
- if (phdr[cnt].p_align == 0)
- bootstrap_map.l_tls_firstbyte_offset = 0;
- else
- bootstrap_map.l_tls_firstbyte_offset = (phdr[cnt].p_vaddr
- & (phdr[cnt].p_align - 1));
- assert (bootstrap_map.l_tls_blocksize != 0);
- bootstrap_map.l_tls_initimage_size = phdr[cnt].p_filesz;
- bootstrap_map.l_tls_initimage = (void *) (bootstrap_map.l_addr
- + phdr[cnt].p_vaddr);
-
- /* We can now allocate the initial TLS block. This can happen
- on the stack. We'll get the final memory later when we
- know all about the various objects loaded at startup
- time. */
-# if TLS_TCB_AT_TP
- tlsblock = alloca (roundup (bootstrap_map.l_tls_blocksize,
- TLS_INIT_TCB_ALIGN)
- + TLS_INIT_TCB_SIZE
- + max_align);
-# elif TLS_DTV_AT_TP
- tlsblock = alloca (roundup (TLS_INIT_TCB_SIZE,
- bootstrap_map.l_tls_align)
- + bootstrap_map.l_tls_blocksize
- + max_align);
-# else
- /* In case a model with a different layout for the TCB and DTV
- is defined add another #elif here and in the following #ifs. */
-# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
-# endif
- /* Align the TLS block. */
- tlsblock = (void *) (((uintptr_t) tlsblock + max_align - 1)
- & ~(max_align - 1));
-
- /* Initialize the dtv. [0] is the length, [1] the generation
- counter. */
- initdtv[0].counter = 1;
- initdtv[1].counter = 0;
-
- /* Initialize the TLS block. */
-# if TLS_TCB_AT_TP
- initdtv[2].pointer = tlsblock;
-# elif TLS_DTV_AT_TP
- bootstrap_map.l_tls_offset = roundup (TLS_INIT_TCB_SIZE,
- bootstrap_map.l_tls_align);
- initdtv[2].pointer = (char *) tlsblock + bootstrap_map.l_tls_offset;
-# else
-# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
-# endif
- p = __mempcpy (initdtv[2].pointer, bootstrap_map.l_tls_initimage,
- bootstrap_map.l_tls_initimage_size);
-# ifdef HAVE_BUILTIN_MEMSET
- __builtin_memset (p, '\0', (bootstrap_map.l_tls_blocksize
- - bootstrap_map.l_tls_initimage_size));
-# else
- {
- size_t remaining = (bootstrap_map.l_tls_blocksize
- - bootstrap_map.l_tls_initimage_size);
- while (remaining-- > 0)
- *p++ = '\0';
- }
-# endif
-
- /* Install the pointer to the dtv. */
-
- /* Initialize the thread pointer. */
-# if TLS_TCB_AT_TP
- bootstrap_map.l_tls_offset
- = roundup (bootstrap_map.l_tls_blocksize, TLS_INIT_TCB_ALIGN);
-
- INSTALL_DTV ((char *) tlsblock + bootstrap_map.l_tls_offset,
- initdtv);
-
- const char *lossage = TLS_INIT_TP ((char *) tlsblock
- + bootstrap_map.l_tls_offset, 0);
-# elif TLS_DTV_AT_TP
- INSTALL_DTV (tlsblock, initdtv);
- const char *lossage = TLS_INIT_TP (tlsblock, 0);
-# else
-# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
-# endif
- if (__builtin_expect (lossage != NULL, 0))
- _dl_fatal_printf ("cannot set up thread-local storage: %s\n",
- lossage);
-
- /* So far this is module number one. */
- bootstrap_map.l_tls_modid = 1;
-
- /* There can only be one PT_TLS entry. */
- break;
- }
-#endif /* USE___THREAD */
-
#ifdef ELF_MACHINE_BEFORE_RTLD_RELOC
ELF_MACHINE_BEFORE_RTLD_RELOC (bootstrap_map.l_info);
#endif
@@ -584,7 +441,7 @@ struct relocate_args
struct map_args
{
/* Argument to map_doit. */
- char *str;
+ const char *str;
struct link_map *loader;
int mode;
/* Return value of map_doit. */
@@ -623,7 +480,8 @@ 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,
+ int type = (args->mode == __RTLD_OPENEXEC) ? lt_executable : lt_library;
+ args->map = _dl_map_object (args->loader, args->str, type, 0,
args->mode, LM_ID_BASE);
}
@@ -634,7 +492,7 @@ dlmopen_doit (void *a)
args->map = _dl_open (args->fname,
(RTLD_LAZY | __RTLD_DLOPEN | __RTLD_AUDIT
| __RTLD_SECURE),
- dl_main, LM_ID_NEWLM, _dl_argc, INTUSE(_dl_argv),
+ dl_main, LM_ID_NEWLM, _dl_argc, _dl_argv,
__environ);
}
@@ -771,15 +629,9 @@ cannot allocate TLS data structures for initial thread");
so it knows not to pass this dtv to the normal realloc. */
GL(dl_initial_dtv) = GET_DTV (tcbp);
- /* And finally install it for the main thread. If ld.so itself uses
- TLS we know the thread pointer was initialized earlier. */
- const char *lossage
-#ifdef USE___THREAD
- = TLS_INIT_TP (tcbp, USE___THREAD);
-#else
- = TLS_INIT_TP (tcbp, 0);
-#endif
- if (__builtin_expect (lossage != NULL, 0))
+ /* And finally install it for the main thread. */
+ const char *lossage = TLS_INIT_TP (tcbp);
+ if (__glibc_unlikely (lossage != NULL))
_dl_fatal_printf ("cannot set up thread-local storage: %s\n", lossage);
tls_init_tp_called = true;
@@ -799,7 +651,7 @@ _dl_initial_error_catch_tsd (void)
static unsigned int
-do_preload (char *fname, struct link_map *main_map, const char *where)
+do_preload (const char *fname, struct link_map *main_map, const char *where)
{
const char *objname;
const char *err_str = NULL;
@@ -813,7 +665,7 @@ do_preload (char *fname, struct link_map *main_map, const char *where)
unsigned int old_nloaded = GL(dl_ns)[LM_ID_BASE]._ns_nloaded;
(void) _dl_catch_error (&objname, &err_str, &malloced, map_doit, &args);
- if (__builtin_expect (err_str != NULL, 0))
+ if (__glibc_unlikely (err_str != NULL))
{
_dl_error_printf ("\
ERROR: ld.so: object '%s' from %s cannot be preloaded (%s): ignored.\n",
@@ -926,7 +778,7 @@ dl_main (const ElfW(Phdr) *phdr,
#ifndef HAVE_INLINED_SYSCALLS
/* Set up a flag which tells we are just starting. */
- INTUSE(_dl_starting_up) = 1;
+ _dl_starting_up = 1;
#endif
if (*user_entry == (ElfW(Addr)) ENTRY_POINT)
@@ -952,55 +804,55 @@ dl_main (const ElfW(Phdr) *phdr,
GL(dl_rtld_map).l_name = rtld_progname;
while (_dl_argc > 1)
- if (! strcmp (INTUSE(_dl_argv)[1], "--list"))
+ if (! strcmp (_dl_argv[1], "--list"))
{
mode = list;
GLRO(dl_lazy) = -1; /* This means do no dependency analysis. */
++_dl_skip_args;
--_dl_argc;
- ++INTUSE(_dl_argv);
+ ++_dl_argv;
}
- else if (! strcmp (INTUSE(_dl_argv)[1], "--verify"))
+ else if (! strcmp (_dl_argv[1], "--verify"))
{
mode = verify;
++_dl_skip_args;
--_dl_argc;
- ++INTUSE(_dl_argv);
+ ++_dl_argv;
}
- else if (! strcmp (INTUSE(_dl_argv)[1], "--inhibit-cache"))
+ else if (! strcmp (_dl_argv[1], "--inhibit-cache"))
{
GLRO(dl_inhibit_cache) = 1;
++_dl_skip_args;
--_dl_argc;
- ++INTUSE(_dl_argv);
+ ++_dl_argv;
}
- else if (! strcmp (INTUSE(_dl_argv)[1], "--library-path")
+ else if (! strcmp (_dl_argv[1], "--library-path")
&& _dl_argc > 2)
{
- library_path = INTUSE(_dl_argv)[2];
+ library_path = _dl_argv[2];
_dl_skip_args += 2;
_dl_argc -= 2;
- INTUSE(_dl_argv) += 2;
+ _dl_argv += 2;
}
- else if (! strcmp (INTUSE(_dl_argv)[1], "--inhibit-rpath")
+ else if (! strcmp (_dl_argv[1], "--inhibit-rpath")
&& _dl_argc > 2)
{
- GLRO(dl_inhibit_rpath) = INTUSE(_dl_argv)[2];
+ GLRO(dl_inhibit_rpath) = _dl_argv[2];
_dl_skip_args += 2;
_dl_argc -= 2;
- INTUSE(_dl_argv) += 2;
+ _dl_argv += 2;
}
- else if (! strcmp (INTUSE(_dl_argv)[1], "--audit") && _dl_argc > 2)
+ else if (! strcmp (_dl_argv[1], "--audit") && _dl_argc > 2)
{
- process_dl_audit (INTUSE(_dl_argv)[2]);
+ process_dl_audit (_dl_argv[2]);
_dl_skip_args += 2;
_dl_argc -= 2;
- INTUSE(_dl_argv) += 2;
+ _dl_argv += 2;
}
else
break;
@@ -1034,7 +886,7 @@ of this helper program; chances are you did not intend to run this program.\n\
++_dl_skip_args;
--_dl_argc;
- ++INTUSE(_dl_argv);
+ ++_dl_argv;
/* The initialization of _dl_stack_flags done below assumes the
executable's PT_GNU_STACK may have been honored by the kernel, and
@@ -1067,7 +919,7 @@ of this helper program; chances are you did not intend to run this program.\n\
args.mode = __RTLD_OPENEXEC;
(void) _dl_catch_error (&objname, &err_str, &malloced, map_doit,
&args);
- if (__builtin_expect (err_str != NULL, 0))
+ if (__glibc_unlikely (err_str != NULL))
/* We don't free the returned string, the programs stops
anyway. */
_exit (EXIT_FAILURE);
@@ -1075,7 +927,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, lt_executable, 0,
__RTLD_OPENEXEC, LM_ID_BASE);
HP_TIMING_NOW (stop);
@@ -1370,10 +1222,25 @@ of this helper program; chances are you did not intend to run this program.\n\
GLRO(dl_use_load_bias) = main_map->l_addr == 0 ? -1 : 0;
/* Set up the program header information for the dynamic linker
- itself. It is needed in the dl_iterate_phdr() callbacks. */
- ElfW(Ehdr) *rtld_ehdr = (ElfW(Ehdr) *) GL(dl_rtld_map).l_map_start;
- ElfW(Phdr) *rtld_phdr = (ElfW(Phdr) *) (GL(dl_rtld_map).l_map_start
- + rtld_ehdr->e_phoff);
+ itself. It is needed in the dl_iterate_phdr callbacks. */
+ const ElfW(Ehdr) *rtld_ehdr;
+
+ /* Starting from binutils-2.23, the linker will define the magic symbol
+ __ehdr_start to point to our own ELF header if it is visible in a
+ segment that also includes the phdrs. If that's not available, we use
+ the old method that assumes the beginning of the file is part of the
+ lowest-addressed PT_LOAD segment. */
+#ifdef HAVE_EHDR_START
+ extern const ElfW(Ehdr) __ehdr_start __attribute__ ((visibility ("hidden")));
+ rtld_ehdr = &__ehdr_start;
+#else
+ rtld_ehdr = (void *) GL(dl_rtld_map).l_map_start;
+#endif
+ assert (rtld_ehdr->e_ehsize == sizeof *rtld_ehdr);
+ assert (rtld_ehdr->e_phentsize == sizeof (ElfW(Phdr)));
+
+ const ElfW(Phdr) *rtld_phdr = (const void *) rtld_ehdr + rtld_ehdr->e_phoff;
+
GL(dl_rtld_map).l_phdr = rtld_phdr;
GL(dl_rtld_map).l_phnum = rtld_ehdr->e_phnum;
@@ -1394,7 +1261,7 @@ of this helper program; chances are you did not intend to run this program.\n\
GL(dl_rtld_map).l_tls_modid = _dl_next_tls_modid ();
/* If we have auditing DSOs to load, do it now. */
- if (__builtin_expect (audit_list != NULL, 0))
+ if (__glibc_unlikely (audit_list != NULL))
{
/* Iterate over all entries in the list. The order is important. */
struct audit_ifaces *last_audit = NULL;
@@ -1428,7 +1295,7 @@ of this helper program; chances are you did not intend to run this program.\n\
bool malloced;
(void) _dl_catch_error (&objname, &err_str, &malloced, dlmopen_doit,
&dlmargs);
- if (__builtin_expect (err_str != NULL, 0))
+ if (__glibc_unlikely (err_str != NULL))
{
not_loaded:
_dl_error_printf ("\
@@ -1544,7 +1411,7 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
/* If we have any auditing modules, announce that we already
have two objects loaded. */
- if (__builtin_expect (GLRO(dl_naudit) > 0, 0))
+ if (__glibc_unlikely (GLRO(dl_naudit) > 0))
{
struct link_map *ls[2] = { main_map, &GL(dl_rtld_map) };
@@ -1569,6 +1436,10 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
}
}
+ /* Keep track of the currently loaded modules to count how many
+ non-audit modules which use TLS are loaded. */
+ size_t count_modids = _dl_count_modids ();
+
/* Set up debugging before the debugger is notified for the first time. */
#ifdef ELF_MACHINE_DEBUG_SETUP
/* Some machines (e.g. MIPS) don't use DT_DEBUG in this way. */
@@ -1593,7 +1464,7 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
/* Auditing checkpoint: we are ready to signal that the initial map
is being constructed. */
- if (__builtin_expect (GLRO(dl_naudit) > 0, 0))
+ if (__glibc_unlikely (GLRO(dl_naudit) > 0))
{
struct audit_ifaces *afct = GLRO(dl_audit);
for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
@@ -1612,7 +1483,7 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
struct link_map **preloads = NULL;
unsigned int npreloads = 0;
- if (__builtin_expect (preloadlist != NULL, 0))
+ if (__glibc_unlikely (preloadlist != NULL))
{
/* The LD_PRELOAD environment variable gives list of libraries
separated by white space or colons that are loaded before the
@@ -1627,7 +1498,7 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
/* Prevent optimizing strsep. Speed is not important here. */
while ((p = (strsep) (&list, " :")) != NULL)
if (p[0] != '\0'
- && (__builtin_expect (! INTUSE(__libc_enable_secure), 1)
+ && (__builtin_expect (! __libc_enable_secure, 1)
|| strchr (p, '/') == NULL))
npreloads += do_preload (p, main_map, "LD_PRELOAD");
@@ -1643,12 +1514,12 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
the work but this does not matter, since it is not for production
use. */
static const char preload_file[] = "/etc/ld.so.preload";
- if (__builtin_expect (__access (preload_file, R_OK) == 0, 0))
+ if (__glibc_unlikely (__access (preload_file, R_OK) == 0))
{
/* Read the contents of the file. */
file = _dl_sysdep_read_whole_file (preload_file, &file_size,
PROT_READ | PROT_WRITE);
- if (__builtin_expect (file != MAP_FAILED, 0))
+ if (__glibc_unlikely (file != MAP_FAILED))
{
/* Parse the file. It contains names of libraries to be loaded,
separated by white spaces or `:'. It may also contain
@@ -1720,7 +1591,7 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
}
}
- if (__builtin_expect (*first_preload != NULL, 0))
+ if (__glibc_unlikely (*first_preload != NULL))
{
/* Set up PRELOADS with a vector of the preloaded libraries. */
struct link_map *l = *first_preload;
@@ -1757,7 +1628,7 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
break;
bool rtld_multiple_ref = false;
- if (__builtin_expect (i < main_map->l_searchlist.r_nlist, 1))
+ if (__glibc_likely (i < main_map->l_searchlist.r_nlist))
{
/* Some DT_NEEDED entry referred to the interpreter object itself, so
put it back in the list of visible objects. We insert it into the
@@ -1815,7 +1686,7 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
if (tcbp == NULL)
tcbp = init_tls ();
- if (__builtin_expect (audit_list == NULL, 1))
+ if (__glibc_likely (audit_list == NULL))
/* Initialize security features. But only if we have not done it
earlier. */
security_init ();
@@ -1929,7 +1800,7 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
ElfW(Addr) loadbase;
lookup_t result;
- result = _dl_lookup_symbol_x (INTUSE(_dl_argv)[i], main_map,
+ result = _dl_lookup_symbol_x (_dl_argv[i], main_map,
&ref, main_map->l_scope,
NULL, ELF_RTYPE_CLASS_PLT,
DL_LOOKUP_ADD_DEPENDENCY, NULL);
@@ -1937,7 +1808,7 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
loadbase = LOOKUP_VALUE_ADDRESS (result);
_dl_printf ("%s found at 0x%0*Zd in object at 0x%0*Zd\n",
- INTUSE(_dl_argv)[i],
+ _dl_argv[i],
(int) sizeof ref->st_value * 2,
(size_t) ref->st_value,
(int) sizeof loadbase * 2, (size_t) loadbase);
@@ -2099,7 +1970,7 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
if (r_list == r_listend && liblist == liblistend)
prelinked = true;
- if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_LIBS, 0))
+ if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_LIBS))
_dl_debug_printf ("\nprelink checking: %s\n",
prelinked ? "ok" : "failed");
}
@@ -2117,7 +1988,7 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
GLRO(dl_init_all_dirs) = GL(dl_all_dirs);
/* Print scope information. */
- if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_SCOPES, 0))
+ if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_SCOPES))
{
_dl_debug_printf ("\nInitial object scopes\n");
@@ -2215,12 +2086,13 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
this has to go here because the calls it makes should use the
rtld versions of the functions (particularly calloc()), but it
needs to have _dl_profile_map set up by the relocator. */
- if (__builtin_expect (GL(dl_profile_map) != NULL, 0))
+ if (__glibc_unlikely (GL(dl_profile_map) != NULL))
/* We must prepare the profiling. */
_dl_start_profile ();
}
- if (!was_tls_init_tp_called && GL(dl_tls_max_dtv_idx) > 0)
+ if ((!was_tls_init_tp_called && GL(dl_tls_max_dtv_idx) > 0)
+ || count_modids != _dl_count_modids ())
++GL(dl_tls_generation);
/* Now that we have completed relocation, the initializer data
@@ -2228,17 +2100,11 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
into the main thread's TLS area, which we allocated above. */
_dl_allocate_tls_init (tcbp);
- /* And finally install it for the main thread. If ld.so itself uses
- TLS we know the thread pointer was initialized earlier. */
+ /* And finally install it for the main thread. */
if (! tls_init_tp_called)
{
- const char *lossage
-#ifdef USE___THREAD
- = TLS_INIT_TP (tcbp, USE___THREAD);
-#else
- = TLS_INIT_TP (tcbp, 0);
-#endif
- if (__builtin_expect (lossage != NULL, 0))
+ const char *lossage = TLS_INIT_TP (tcbp);
+ if (__glibc_unlikely (lossage != NULL))
_dl_fatal_printf ("cannot set up thread-local storage: %s\n",
lossage);
}
@@ -2279,7 +2145,7 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
#ifdef SHARED
/* Auditing checkpoint: we have added all objects. */
- if (__builtin_expect (GLRO(dl_naudit) > 0, 0))
+ if (__glibc_unlikely (GLRO(dl_naudit) > 0))
{
struct link_map *head = GL(dl_ns)[LM_ID_BASE]._ns_loaded;
/* Do not call the functions for any auditing object. */
@@ -2452,7 +2318,7 @@ process_dl_audit (char *str)
while ((p = (strsep) (&str, ":")) != NULL)
if (p[0] != '\0'
- && (__builtin_expect (! INTUSE(__libc_enable_secure), 1)
+ && (__builtin_expect (! __libc_enable_secure, 1)
|| strchr (p, '/') == NULL))
{
/* This is using the local malloc, not the system malloc. The
@@ -2486,7 +2352,7 @@ process_envvars (enum mode *modep)
/* This is the default place for profiling data file. */
GLRO(dl_profile_output)
- = &"/var/tmp\0/var/profile"[INTUSE(__libc_enable_secure) ? 9 : 0];
+ = &"/var/tmp\0/var/profile"[__libc_enable_secure ? 9 : 0];
while ((envline = _dl_next_ld_env_entry (&runp)) != NULL)
{
@@ -2554,7 +2420,7 @@ process_envvars (enum mode *modep)
case 9:
/* Test whether we want to see the content of the auxiliary
array passed up from the kernel. */
- if (!INTUSE(__libc_enable_secure)
+ if (!__libc_enable_secure
&& memcmp (envline, "SHOW_AUXV", 9) == 0)
_dl_show_auxv ();
break;
@@ -2568,7 +2434,7 @@ process_envvars (enum mode *modep)
case 11:
/* Path where the binary is found. */
- if (!INTUSE(__libc_enable_secure)
+ if (!__libc_enable_secure
&& memcmp (envline, "ORIGIN_PATH", 11) == 0)
GLRO(dl_origin_path) = &envline[12];
break;
@@ -2588,7 +2454,7 @@ process_envvars (enum mode *modep)
break;
}
- if (!INTUSE(__libc_enable_secure)
+ if (!__libc_enable_secure
&& memcmp (envline, "DYNAMIC_WEAK", 12) == 0)
GLRO(dl_dynamic_weak) = 1;
break;
@@ -2599,7 +2465,7 @@ process_envvars (enum mode *modep)
#ifdef EXTRA_LD_ENVVARS_13
EXTRA_LD_ENVVARS_13
#endif
- if (!INTUSE(__libc_enable_secure)
+ if (!__libc_enable_secure
&& memcmp (envline, "USE_LOAD_BIAS", 13) == 0)
{
GLRO(dl_use_load_bias) = envline[14] == '1' ? -1 : 0;
@@ -2612,7 +2478,7 @@ process_envvars (enum mode *modep)
case 14:
/* Where to place the profiling data file. */
- if (!INTUSE(__libc_enable_secure)
+ if (!__libc_enable_secure
&& memcmp (envline, "PROFILE_OUTPUT", 14) == 0
&& envline[15] != '\0')
GLRO(dl_profile_output) = &envline[15];
@@ -2650,7 +2516,7 @@ process_envvars (enum mode *modep)
/* Extra security for SUID binaries. Remove all dangerous environment
variables. */
- if (__builtin_expect (INTUSE(__libc_enable_secure), 0))
+ if (__builtin_expect (__libc_enable_secure, 0))
{
static const char unsecure_envvars[] =
#ifdef EXTRA_UNSECURE_ENVVARS
@@ -2715,7 +2581,7 @@ print_statistics (hp_timing_t *rtld_total_timep)
char *wp;
/* Total time rtld used. */
- if (HP_TIMING_AVAIL)
+ if (HP_SMALL_TIMING_AVAIL)
{
HP_TIMING_PRINT (buf, sizeof (buf), *rtld_total_timep);
_dl_debug_printf ("\nruntime linker statistics:\n"
@@ -2783,7 +2649,7 @@ print_statistics (hp_timing_t *rtld_total_timep)
#ifndef HP_TIMING_NONAVAIL
/* Time spend while loading the object and the dependencies. */
- if (HP_TIMING_AVAIL)
+ if (HP_SMALL_TIMING_AVAIL)
{
char pbuf[30];
HP_TIMING_PRINT (buf, sizeof (buf), load_time);
diff --git a/elf/setup-vdso.h b/elf/setup-vdso.h
index f3716b693d..8f2c70146c 100644
--- a/elf/setup-vdso.h
+++ b/elf/setup-vdso.h
@@ -1,5 +1,5 @@
/* Set up the data structures for the system-supplied DSO.
- Copyright (C) 2012-2014 Free Software Foundation, Inc.
+ Copyright (C) 2012-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
@@ -31,7 +31,7 @@ setup_vdso (struct link_map *main_map __attribute__ ((unused)),
mapped and relocated it normally. */
struct link_map *l = _dl_new_object ((char *) "", "", lt_library, NULL,
0, LM_ID_BASE);
- if (__builtin_expect (l != NULL, 1))
+ if (__glibc_likely (l != NULL))
{
static ElfW(Dyn) dyn_temp[DL_RO_DYN_TEMP_CNT] attribute_relro;
@@ -99,7 +99,7 @@ setup_vdso (struct link_map *main_map __attribute__ ((unused)),
/* Add the vDSO to the object list. */
_dl_add_to_namespace_list (l, LM_ID_BASE);
-# ifdef IS_IN_rtld
+# if IS_IN (rtld)
/* Rearrange the list so this DSO appears after rtld_map. */
assert (l->l_next == NULL);
assert (l->l_prev == main_map);
diff --git a/elf/sln.c b/elf/sln.c
index cc75fbebbf..1a7d24e6dc 100644
--- a/elf/sln.c
+++ b/elf/sln.c
@@ -1,5 +1,5 @@
/* `sln' program to create symbolic links between files.
- Copyright (C) 1998-2014 Free Software Foundation, Inc.
+ Copyright (C) 1998-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
diff --git a/elf/sotruss-lib.c b/elf/sotruss-lib.c
index 5359e4a7b7..3880de32c6 100644
--- a/elf/sotruss-lib.c
+++ b/elf/sotruss-lib.c
@@ -1,5 +1,5 @@
/* Trace calls through PLTs and show caller, callee, and parameters.
- Copyright (C) 2011-2014 Free Software Foundation, Inc.
+ Copyright (C) 2011-2015 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@gmail.com>, 2011.
diff --git a/elf/sotruss.ksh b/elf/sotruss.sh
index 371a70b3e1..c458585ccb 100755
--- a/elf/sotruss.ksh
+++ b/elf/sotruss.sh
@@ -1,5 +1,5 @@
-#! @KSH@
-# Copyright (C) 2011-2014 Free Software Foundation, Inc.
+#! @BASH@
+# Copyright (C) 2011-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
@@ -28,7 +28,7 @@ unset SOTRUSS_NOINDENT
SOTRUSS_WHICH=$$
lib='@PREFIX@/$LIB/audit/sotruss-lib.so'
-function do_help {
+do_help() {
echo $"Usage: sotruss [OPTION...] [--] EXECUTABLE [EXECUTABLE-OPTION...]
-F, --from FROMLIST Trace calls from objects on FROMLIST
-T, --to TOLIST Trace calls to objects on TOLIST
@@ -51,13 +51,13 @@ function do_help {
exit 0
}
-function do_missing_arg {
+do_missing_arg() {
printf >&2 $"%s: option requires an argument -- '%s'\n" sotruss "$1"
printf >&2 $"Try \`%s --help' or \`%s --usage' for more information.\n" sotruss sotruss
exit 1
}
-function do_ambiguous {
+do_ambiguous() {
printf >&2 $"%s: option is ambiguous; possibilities:"
while test $# -gt 0; do
printf >&2 " '%s'" $1
@@ -75,7 +75,7 @@ while test $# -gt 0; do
printf $"Copyright (C) %s Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-" "2014"
+" "2015"
printf $"Written by %s.\n" "Ulrich Drepper"
exit 0
;;
@@ -150,6 +150,3 @@ export SOTRUSS_EXIT
export LD_AUDIT="$lib"
exec "$@"
-# Local Variables:
-# mode:ksh
-# End:
diff --git a/elf/sprof.c b/elf/sprof.c
index 7b47fd765c..ec3fde3848 100644
--- a/elf/sprof.c
+++ b/elf/sprof.c
@@ -1,5 +1,5 @@
/* Read and display shared object profiling data.
- Copyright (C) 1997-2014 Free Software Foundation, Inc.
+ Copyright (C) 1997-2015 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
@@ -391,7 +391,7 @@ Copyright (C) %s Free Software Foundation, Inc.\n\
This is free software; see the source for copying conditions. There is NO\n\
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
"),
- "2014");
+ "2015");
fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
}
@@ -439,7 +439,7 @@ load_shobj (const char *name)
result = (struct shobj *) calloc (1, sizeof (struct shobj));
if (result == NULL)
{
- error (0, errno, _("cannot create internal descriptors"));
+ error (0, errno, _("cannot create internal descriptor"));
dlclose (map);
return NULL;
}
diff --git a/elf/static-stubs.c b/elf/static-stubs.c
index a4edb849eb..3407fe691b 100644
--- a/elf/static-stubs.c
+++ b/elf/static-stubs.c
@@ -1,6 +1,6 @@
/* Stub implementations of functions to link into statically linked
programs without needing libgcc_eh.
- Copyright (C) 2012-2014 Free Software Foundation, Inc.
+ Copyright (C) 2012-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
diff --git a/elf/tlsdeschtab.h b/elf/tlsdeschtab.h
index 9a0f965c5f..fb0eb88e7e 100644
--- a/elf/tlsdeschtab.h
+++ b/elf/tlsdeschtab.h
@@ -1,5 +1,5 @@
/* Hash table for TLS descriptors.
- Copyright (C) 2005-2014 Free Software Foundation, Inc.
+ Copyright (C) 2005-2015 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Alexandre Oliva <aoliva@redhat.com>
@@ -20,6 +20,8 @@
#ifndef TLSDESCHTAB_H
# define TLSDESCHTAB_H 1
+#include <atomic.h>
+
# ifdef SHARED
# include <inline-hashtab.h>
@@ -42,7 +44,7 @@ eq_tlsdesc (void *p, void *q)
return tdp->tlsinfo.ti_offset == tdq->tlsinfo.ti_offset;
}
-inline static int
+inline static size_t
map_generation (struct link_map *map)
{
size_t idx = map->l_tls_modid;
@@ -58,7 +60,7 @@ map_generation (struct link_map *map)
we can assume that, if the generation count is zero, we
still haven't determined the generation count for this
module. */
- if (listp->slotinfo[idx].gen)
+ if (listp->slotinfo[idx].map == map && listp->slotinfo[idx].gen)
return listp->slotinfo[idx].gen;
else
break;
@@ -138,17 +140,17 @@ _dl_make_tlsdesc_dynamic (struct link_map *map, size_t ti_offset)
static int
_dl_tlsdesc_resolve_early_return_p (struct tlsdesc volatile *td, void *caller)
{
- if (caller != td->entry)
+ if (caller != atomic_load_relaxed (&td->entry))
return 1;
__rtld_lock_lock_recursive (GL(dl_load_lock));
- if (caller != td->entry)
+ if (caller != atomic_load_relaxed (&td->entry))
{
__rtld_lock_unlock_recursive (GL(dl_load_lock));
return 1;
}
- td->entry = _dl_tlsdesc_resolve_hold;
+ atomic_store_relaxed (&td->entry, _dl_tlsdesc_resolve_hold);
return 0;
}
diff --git a/elf/tst-align.c b/elf/tst-align.c
index 859f8e7f07..124bc31e20 100644
--- a/elf/tst-align.c
+++ b/elf/tst-align.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003-2014 Free Software Foundation, Inc.
+/* Copyright (C) 2003-2015 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
diff --git a/elf/tst-align2.c b/elf/tst-align2.c
index 8d37be855f..ec16e6e0b0 100644
--- a/elf/tst-align2.c
+++ b/elf/tst-align2.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2005-2014 Free Software Foundation, Inc.
+/* Copyright (C) 2005-2015 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Jakub Jelinek <jakub@redhat.com>, 2005.
diff --git a/elf/tst-alignmod.c b/elf/tst-alignmod.c
index c558beec26..30b5cd1d6d 100644
--- a/elf/tst-alignmod.c
+++ b/elf/tst-alignmod.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003-2014 Free Software Foundation, Inc.
+/* Copyright (C) 2003-2015 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
diff --git a/elf/tst-alignmod2.c b/elf/tst-alignmod2.c
index a936da6e8f..888814688b 100644
--- a/elf/tst-alignmod2.c
+++ b/elf/tst-alignmod2.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003-2014 Free Software Foundation, Inc.
+/* Copyright (C) 2003-2015 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
diff --git a/elf/tst-audit2.c b/elf/tst-audit2.c
index b4fa906940..1d69cd669e 100644
--- a/elf/tst-audit2.c
+++ b/elf/tst-audit2.c
@@ -3,26 +3,35 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <dlfcn.h>
#define MAGIC1 0xabcdef72
#define MAGIC2 0xd8675309
static __thread unsigned int magic[] = { MAGIC1, MAGIC2 };
+static __thread int calloc_called;
#undef calloc
/* This calloc definition will be called by the dynamic linker itself.
- We test that it has initialized our TLS block by the time it does so. */
+ We test that interposed calloc is called by the dynamic loader, and
+ that TLS is fully initialized by then. */
void *
calloc (size_t n, size_t m)
{
- if (magic[0] != MAGIC1 || magic[1] != MAGIC2)
+ if (!calloc_called)
{
- printf ("{%x, %x} != {%x, %x}\n", magic[0], magic[1], MAGIC1, MAGIC2);
- abort ();
+ /* Allow our calloc to be called more than once. */
+ calloc_called = 1;
+ if (magic[0] != MAGIC1 || magic[1] != MAGIC2)
+ {
+ printf ("{%x, %x} != {%x, %x}\n",
+ magic[0], magic[1], MAGIC1, MAGIC2);
+ abort ();
+ }
+ magic[0] = MAGIC2;
+ magic[1] = MAGIC1;
}
- magic[0] = MAGIC2;
- magic[1] = MAGIC1;
n *= m;
void *ptr = malloc (n);
@@ -31,9 +40,14 @@ calloc (size_t n, size_t m)
return ptr;
}
-int
-main (void)
+static int
+do_test (void)
{
+ /* Make sure that our calloc is called from the dynamic linker at least
+ once. */
+ void *h = dlopen("$ORIGIN/tst-auditmod9b.so", RTLD_LAZY);
+ if (h != NULL)
+ dlclose (h);
if (magic[1] != MAGIC1 || magic[0] != MAGIC2)
{
printf ("{%x, %x} != {%x, %x}\n", magic[0], magic[1], MAGIC2, MAGIC1);
@@ -42,3 +56,6 @@ main (void)
return 0;
}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/elf/tst-audit9.c b/elf/tst-audit9.c
new file mode 100644
index 0000000000..7b90a5ad2d
--- /dev/null
+++ b/elf/tst-audit9.c
@@ -0,0 +1,12 @@
+#include <dlfcn.h>
+
+static int
+do_test (void)
+{
+ void *h = dlopen("$ORIGIN/tst-auditmod9b.so", RTLD_LAZY);
+ int (*fp)(void) = dlsym(h, "f");
+ return fp() - 1;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/elf/tst-auditmod9a.c b/elf/tst-auditmod9a.c
new file mode 100644
index 0000000000..7213ade123
--- /dev/null
+++ b/elf/tst-auditmod9a.c
@@ -0,0 +1,15 @@
+#include <stdint.h>
+
+__thread int var;
+
+unsigned int
+la_version (unsigned int v)
+{
+ return v;
+}
+
+void
+la_activity (uintptr_t *cookie, unsigned int flag)
+{
+ ++var;
+}
diff --git a/elf/tst-auditmod9b.c b/elf/tst-auditmod9b.c
new file mode 100644
index 0000000000..8eeeb49986
--- /dev/null
+++ b/elf/tst-auditmod9b.c
@@ -0,0 +1,6 @@
+__thread int a;
+
+int f(void)
+{
+ return ++a;
+}
diff --git a/elf/tst-auxv.c b/elf/tst-auxv.c
index cf17e70247..79b12a5f30 100644
--- a/elf/tst-auxv.c
+++ b/elf/tst-auxv.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2013-2014 Free Software Foundation, Inc.
+/* Copyright (C) 2013-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
diff --git a/elf/tst-dl-iter-static.c b/elf/tst-dl-iter-static.c
new file mode 100644
index 0000000000..fa83526d6d
--- /dev/null
+++ b/elf/tst-dl-iter-static.c
@@ -0,0 +1,47 @@
+/* BZ #16046 dl_iterate_phdr static executable test.
+ Copyright (C) 2014-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 <link.h>
+
+/* Check that the link map of the static executable itself is iterated
+ over exactly once. */
+
+static int
+callback (struct dl_phdr_info *info, size_t size, void *data)
+{
+ int *count = data;
+
+ if (info->dlpi_name[0] == '\0')
+ (*count)++;
+
+ return 0;
+}
+
+static int
+do_test (void)
+{
+ int count = 0;
+ int status;
+
+ status = dl_iterate_phdr (callback, &count);
+
+ return status || count != 1;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/elf/tst-dlmodcount.c b/elf/tst-dlmodcount.c
index 90883954e2..64df2fa18a 100644
--- a/elf/tst-dlmodcount.c
+++ b/elf/tst-dlmodcount.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2004-2014 Free Software Foundation, Inc.
+/* Copyright (C) 2004-2015 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by David Mosberger <davidm@hpl.hp.com>, 2004.
diff --git a/elf/tst-dlopen-aout.c b/elf/tst-dlopen-aout.c
new file mode 100644
index 0000000000..1281bdff03
--- /dev/null
+++ b/elf/tst-dlopen-aout.c
@@ -0,0 +1,67 @@
+/* Test case for BZ #16634.
+
+ Verify that incorrectly dlopen()ing an executable without
+ __RTLD_OPENEXEC does not cause assertion in ld.so.
+
+ Copyright (C) 2014-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/>.
+
+ Note: this test currently only fails when glibc is configured with
+ --enable-hardcoded-path-in-tests. */
+
+#include <assert.h>
+#include <dlfcn.h>
+#include <stdio.h>
+#include <pthread.h>
+
+__thread int x;
+
+void *
+fn (void *p)
+{
+ return p;
+}
+
+static int
+do_test (int argc, char *argv[])
+{
+ int j;
+
+ for (j = 0; j < 100; ++j)
+ {
+ pthread_t thr;
+ void *p;
+ int rc;
+
+ p = dlopen (argv[0], RTLD_LAZY);
+ if (p != NULL)
+ {
+ fprintf (stderr, "dlopen unexpectedly succeeded\n");
+ return 1;
+ }
+ rc = pthread_create (&thr, NULL, fn, NULL);
+ assert (rc == 0);
+
+ rc = pthread_join (thr, NULL);
+ assert (rc == 0);
+ }
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test (argc, argv)
+#include "../test-skeleton.c"
diff --git a/elf/tst-dlopenrpath.c b/elf/tst-dlopenrpath.c
index 9363105d39..04decbe629 100644
--- a/elf/tst-dlopenrpath.c
+++ b/elf/tst-dlopenrpath.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2004-2014 Free Software Foundation, Inc.
+/* Copyright (C) 2004-2015 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2004.
diff --git a/elf/tst-dlopenrpathmod.c b/elf/tst-dlopenrpathmod.c
index c2ff6c1925..bf0f6be4c2 100644
--- a/elf/tst-dlopenrpathmod.c
+++ b/elf/tst-dlopenrpathmod.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2004-2014 Free Software Foundation, Inc.
+/* Copyright (C) 2004-2015 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2004.
diff --git a/elf/tst-global1.c b/elf/tst-global1.c
index 1611b51b67..4df335c637 100644
--- a/elf/tst-global1.c
+++ b/elf/tst-global1.c
@@ -1,8 +1,8 @@
#include <dlfcn.h>
#include <stdio.h>
-int
-main (void)
+static int
+do_test (void)
{
void *h1 = dlopen ("$ORIGIN/testobj6.so", RTLD_GLOBAL|RTLD_LAZY);
if (h1 == NULL)
@@ -34,3 +34,6 @@ main (void)
return 0;
}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/elf/tst-leaks1.c b/elf/tst-leaks1.c
index 36e4aee9cf..dcff28dafa 100644
--- a/elf/tst-leaks1.c
+++ b/elf/tst-leaks1.c
@@ -3,8 +3,8 @@
#include <mcheck.h>
#include <stdlib.h>
-int
-main (void)
+static int
+do_test (void)
{
mtrace ();
@@ -23,3 +23,6 @@ main (void)
return ret;
}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/elf/tst-nodelete-opened-lib.c b/elf/tst-nodelete-opened-lib.c
new file mode 100644
index 0000000000..994702a9c5
--- /dev/null
+++ b/elf/tst-nodelete-opened-lib.c
@@ -0,0 +1,19 @@
+/* Verify that objects opened with RTLD_NODELETE are not unloaded - the DSO.
+ 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/>. */
+
+int foo_var = 42;
diff --git a/elf/tst-nodelete-opened.c b/elf/tst-nodelete-opened.c
new file mode 100644
index 0000000000..501d005f81
--- /dev/null
+++ b/elf/tst-nodelete-opened.c
@@ -0,0 +1,69 @@
+/* Verify that an already opened DSO opened agained with RTLD_NODELETE actually
+ sets the NODELETE flag.
+
+ 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 <stdio.h>
+
+int
+do_test (void)
+{
+ void *h1 = dlopen ("$ORIGIN/tst-nodelete-opened-lib.so", RTLD_LAZY);
+ if (h1 == NULL)
+ {
+ printf ("h1: failed to open DSO: %s\n", dlerror ());
+ return 1;
+ }
+
+ void *h2 = dlopen ("$ORIGIN/tst-nodelete-opened-lib.so",
+ RTLD_LAZY | RTLD_NODELETE);
+ if (h2 == NULL)
+ {
+ printf ("h2: failed to open DSO: %s\n", dlerror ());
+ return 1;
+ }
+
+ int *foo = dlsym (h2, "foo_var");
+ if (foo == NULL)
+ {
+ printf ("failed to load symbol foo_var: %s\n", dlerror ());
+ return 1;
+ }
+
+ if (dlclose (h1) != 0)
+ {
+ printf ("h1: dlclose failed: %s\n", dlerror ());
+ return 1;
+ }
+
+ if (dlclose (h2) != 0)
+ {
+ printf ("h2: dlclose failed: %s\n", dlerror ());
+ return 1;
+ }
+
+ /* This FOO dereference will crash with a segfault if the DSO was
+ unloaded. */
+ printf ("foo == %d\n", *foo);
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/elf/tst-nodelete-rtldmod.cc b/elf/tst-nodelete-rtldmod.cc
new file mode 100644
index 0000000000..740e1d8181
--- /dev/null
+++ b/elf/tst-nodelete-rtldmod.cc
@@ -0,0 +1,6 @@
+extern int not_exist (void);
+
+int foo (void)
+{
+ return not_exist ();
+}
diff --git a/elf/tst-nodelete-uniquemod.cc b/elf/tst-nodelete-uniquemod.cc
new file mode 100644
index 0000000000..632b303d58
--- /dev/null
+++ b/elf/tst-nodelete-uniquemod.cc
@@ -0,0 +1,14 @@
+extern int not_exist (void);
+
+inline int make_unique (void)
+{
+ /* Static variables in inline functions and classes
+ generate STB_GNU_UNIQUE symbols. */
+ static int unique;
+ return ++unique;
+}
+
+int foo (void)
+{
+ return make_unique () + not_exist ();
+}
diff --git a/elf/tst-nodelete-zmod.cc b/elf/tst-nodelete-zmod.cc
new file mode 100644
index 0000000000..740e1d8181
--- /dev/null
+++ b/elf/tst-nodelete-zmod.cc
@@ -0,0 +1,6 @@
+extern int not_exist (void);
+
+int foo (void)
+{
+ return not_exist ();
+}
diff --git a/elf/tst-nodelete.cc b/elf/tst-nodelete.cc
new file mode 100644
index 0000000000..176cb68836
--- /dev/null
+++ b/elf/tst-nodelete.cc
@@ -0,0 +1,51 @@
+#include "../dlfcn/dlfcn.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+static int
+do_test (void)
+{
+ int result = 0;
+
+ /* This is a test for correct handling of dlopen failures for library that
+ is loaded with RTLD_NODELETE flag. The first dlopen should fail because
+ of undefined symbols in shared library. The second dlopen then verifies
+ that library was properly unloaded. */
+ if (dlopen ("tst-nodelete-rtldmod.so", RTLD_NOW | RTLD_NODELETE) != NULL
+ || dlopen ("tst-nodelete-rtldmod.so", RTLD_LAZY | RTLD_NOLOAD) != NULL)
+ {
+ printf ("RTLD_NODELETE test failed\n");
+ result = 1;
+ }
+
+ /* This is a test for correct handling of dlopen failures for library that
+ is linked with '-z nodelete' option and hence has DF_1_NODELETE flag.
+ The first dlopen should fail because of undefined symbols in shared
+ library. The second dlopen then verifies that library was properly
+ unloaded. */
+ if (dlopen ("tst-nodelete-zmod.so", RTLD_NOW) != NULL
+ || dlopen ("tst-nodelete-zmod.so", RTLD_LAZY | RTLD_NOLOAD) != NULL)
+ {
+ printf ("-z nodelete test failed\n");
+ result = 1;
+ }
+
+ /* This is a test for correct handling of dlopen failures for library
+ with unique symbols. The first dlopen should fail because of undefined
+ symbols in shared library. The second dlopen then verifies that library
+ was properly unloaded. */
+ if (dlopen ("tst-nodelete-uniquemod.so", RTLD_NOW) != NULL
+ || dlopen ("tst-nodelete-uniquemod.so", RTLD_LAZY | RTLD_NOLOAD) != NULL)
+ {
+ printf ("Unique symbols test failed\n");
+ result = 1;
+ }
+
+ if (result == 0)
+ printf ("SUCCESS\n");
+
+ return result;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/elf/tst-null-argv-lib.c b/elf/tst-null-argv-lib.c
index 6de150b965..a1953b69eb 100644
--- a/elf/tst-null-argv-lib.c
+++ b/elf/tst-null-argv-lib.c
@@ -1,6 +1,6 @@
/* Verify that program does not crash when LD_DEBUG is set and the program name
is not available. This is the library.
- Copyright (C) 2013-2014 Free Software Foundation, Inc.
+ Copyright (C) 2013-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
diff --git a/elf/tst-null-argv.c b/elf/tst-null-argv.c
index 20df053edc..2e0e6bc155 100644
--- a/elf/tst-null-argv.c
+++ b/elf/tst-null-argv.c
@@ -1,6 +1,6 @@
/* Verify that program does not crash when LD_DEBUG is set and the program name
is not available.
- Copyright (C) 2013-2014 Free Software Foundation, Inc.
+ Copyright (C) 2013-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
diff --git a/elf/tst-pathopt.c b/elf/tst-pathopt.c
index 1f7aac2a41..8d73ad4def 100644
--- a/elf/tst-pathopt.c
+++ b/elf/tst-pathopt.c
@@ -4,8 +4,8 @@
#include <stdlib.h>
-int
-main (void)
+static int
+do_test (void)
{
void *h;
int (*fp) (int);
@@ -37,3 +37,6 @@ main (void)
return result;
}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/elf/tst-pathopt.sh b/elf/tst-pathopt.sh
index 9677cf0ae8..85d0be262d 100755
--- a/elf/tst-pathopt.sh
+++ b/elf/tst-pathopt.sh
@@ -1,6 +1,6 @@
#! /bin/sh
# Test lookup path optimization.
-# 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.
# The GNU C Library is free software; you can redistribute it and/or
@@ -21,6 +21,7 @@ set -e
common_objpfx=$1
test_wrapper_env=$2
+run_program_env=$3
test -e ${common_objpfx}elf/will-be-empty &&
rm -fr ${common_objpfx}elf/will-be-empty
@@ -30,8 +31,8 @@ test -d ${common_objpfx}elf/for-renamed ||
cp ${common_objpfx}elf/pathoptobj.so ${common_objpfx}elf/for-renamed/renamed.so
${test_wrapper_env} \
-LOCPATH=${common_objpfx}localedata GCONV_PATH=${common_objpfx}iconvdata \
-LC_ALL=C LD_LIBRARY_PATH=${common_objpfx}elf/will-be-empty:${common_objpfx}elf/for-renamed:${common_objpfx}.:${common_objpfx}dlfcn \
+${run_program_env} \
+LD_LIBRARY_PATH=${common_objpfx}elf/will-be-empty:${common_objpfx}elf/for-renamed:${common_objpfx}.:${common_objpfx}dlfcn \
${common_objpfx}elf/ld.so ${common_objpfx}elf/tst-pathopt \
> ${common_objpfx}elf/tst-pathopt.out
diff --git a/elf/tst-pie2.c b/elf/tst-pie2.c
new file mode 100644
index 0000000000..b76b3236e4
--- /dev/null
+++ b/elf/tst-pie2.c
@@ -0,0 +1,38 @@
+/* Test case for BZ #16381
+
+ Copyright (C) 2014-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 <assert.h>
+
+static int g;
+
+void init_g (void) __attribute__((constructor));
+
+void
+init_g (void)
+{
+ assert (g == 0);
+ g += 1;
+}
+
+int
+main (int argc, char *argv[])
+{
+ return 0;
+}
diff --git a/elf/tst-piemod1.c b/elf/tst-piemod1.c
index ad439da800..6e98b5f0c2 100644
--- a/elf/tst-piemod1.c
+++ b/elf/tst-piemod1.c
@@ -6,8 +6,8 @@ foo (void)
return 21;
}
-int
-main (void)
+static int
+do_test (void)
{
int val = foo ();
if (val != 34)
@@ -18,3 +18,6 @@ main (void)
return 0;
}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/elf/tst-protected1a.c b/elf/tst-protected1a.c
new file mode 100644
index 0000000000..f4e76895a9
--- /dev/null
+++ b/elf/tst-protected1a.c
@@ -0,0 +1,236 @@
+/* Test the protected visibility when main is linked with moda and modb
+ in that order:
+ 1. Protected symbols, protected1, protected2 and protected3, defined
+ in moda, are used in moda.
+ 2. Protected symbol, protected3, defined in modb, are used in modb.
+ 3. Symbol, protected1, defined in moda, is also used in main and modb.
+ 4. Symbol, protected2, defined in main, is used in main.
+ 5. Symbol, protected3, defined in moda, is also used in main.
+
+ 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/>. */
+
+/* This file must be compiled as PIE to avoid copy relocation when
+ accessing protected symbols defined in shared libaries since copy
+ relocation doesn't work with protected symbols and linker in
+ binutils 2.26 enforces this rule. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "tst-protected1mod.h"
+
+/* Prototype for our test function. */
+extern int do_test (void);
+
+int protected2 = -1;
+
+#define TEST_FUNCTION do_test ()
+
+/* This defines the `main' function and some more. */
+#include <test-skeleton.c>
+
+int
+do_test (void)
+{
+ int res = 0;
+
+ /* Check if we get the same address for the protected data symbol. */
+ if (&protected1 != protected1a_p ())
+ {
+ puts ("`protected1' in main and moda doesn't have same address");
+ res = 1;
+ }
+ if (&protected1 != protected1b_p ())
+ {
+ puts ("`protected1' in main and modb doesn't have same address");
+ res = 1;
+ }
+
+ /* Check if we get the right value for the protected data symbol. */
+ if (protected1 != 3)
+ {
+ puts ("`protected1' in main and moda doesn't have same value");
+ res = 1;
+ }
+
+ /* Check if we get the right value for data defined in executable. */
+ if (protected2 != -1)
+ {
+ puts ("`protected2' in main has the wrong value");
+ res = 1;
+ }
+
+ /* Check `protected1' in moda. */
+ if (!check_protected1 ())
+ {
+ puts ("`protected1' in moda has the wrong value");
+ res = 1;
+ }
+
+ /* Check `protected2' in moda. */
+ if (!check_protected2 ())
+ {
+ puts ("`protected2' in moda has the wrong value");
+ res = 1;
+ }
+
+ /* Check if we get the same address for the protected data symbol. */
+ if (&protected3 != protected3a_p ())
+ {
+ puts ("`protected3' in main and moda doesn't have same address");
+ res = 1;
+ }
+ if (&protected3 == protected3b_p ())
+ {
+ puts ("`protected3' in main and modb has same address");
+ res = 1;
+ }
+
+ /* Check if we get the right value for the protected data symbol. */
+ if (protected3 != 5)
+ {
+ puts ("`protected3' in main and moda doesn't have same value");
+ res = 1;
+ }
+
+ /* Check `protected3' in moda. */
+ if (!check_protected3a ())
+ {
+ puts ("`protected3' in moda has the wrong value");
+ res = 1;
+ }
+
+ /* Check `protected3' in modb. */
+ if (!check_protected3b ())
+ {
+ puts ("`protected3' in modb has the wrong value");
+ res = 1;
+ }
+
+ /* Set `protected2' in moda to 30. */
+ set_protected2 (300);
+
+ /* Check `protected2' in moda. */
+ if (!check_protected2 ())
+ {
+ puts ("`protected2' in moda has the wrong value");
+ res = 1;
+ }
+
+ /* Set `protected1' in moda to 30. */
+ set_protected1a (30);
+
+ /* Check `protected1' in moda. */
+ if (!check_protected1 ())
+ {
+ puts ("`protected1' in moda has the wrong value");
+ res = 1;
+ }
+
+ /* Check if we get the updated value for the protected data symbol. */
+ if (protected1 != 30)
+ {
+ puts ("`protected1' in main doesn't have the updated value");
+ res = 1;
+ }
+
+ protected2 = -300;
+
+ /* Check `protected2' in moda. */
+ if (!check_protected2 ())
+ {
+ puts ("`protected2' in moda has the wrong value");
+ res = 1;
+ }
+
+ /* Check if data defined in executable is changed. */
+ if (protected2 != -300)
+ {
+ puts ("`protected2' in main is changed");
+ res = 1;
+ }
+
+ /* Set `protected1' in modb to 40. */
+ set_protected1b (40);
+ set_expected_protected1 (40);
+
+ /* Check `protected1' in moda. */
+ if (!check_protected1 ())
+ {
+ puts ("`protected1' in moda has the wrong value");
+ res = 1;
+ }
+
+ /* Check if we get the updated value for the protected data symbol. */
+ if (protected1 != 40)
+ {
+ puts ("`protected1' in main doesn't have the updated value");
+ res = 1;
+ }
+
+ /* Set `protected3' in moda to 80. */
+ set_protected3a (80);
+
+ /* Check `protected3' in moda. */
+ if (!check_protected3a ())
+ {
+ puts ("`protected3' in moda has the wrong value");
+ res = 1;
+ }
+
+ /* Check if we get the updated value for the protected data symbol. */
+ if (protected3 != 80)
+ {
+ puts ("`protected3' in main doesn't have the updated value");
+ res = 1;
+ }
+
+ /* Check `protected3' in modb. */
+ if (!check_protected3b ())
+ {
+ puts ("`protected3' in modb has the wrong value");
+ res = 1;
+ }
+
+ /* Set `protected3' in modb to 100. */
+ set_protected3b (100);
+
+ /* Check `protected3' in moda. */
+ if (!check_protected3a ())
+ {
+ puts ("`protected3' in moda has the wrong value");
+ res = 1;
+ }
+
+ /* Check if we get the updated value for the protected data symbol. */
+ if (protected3 != 80)
+ {
+ puts ("`protected3' in main doesn't have the updated value");
+ res = 1;
+ }
+
+ /* Check `protected3' in modb. */
+ if (!check_protected3b ())
+ {
+ puts ("`protected3' in modb has the wrong value");
+ res = 1;
+ }
+
+ return res;
+}
diff --git a/elf/tst-protected1b.c b/elf/tst-protected1b.c
new file mode 100644
index 0000000000..56352c406f
--- /dev/null
+++ b/elf/tst-protected1b.c
@@ -0,0 +1,242 @@
+/* Test the protected visibility when main is linked with modb and moda
+ in that order:
+ 1. Protected symbols, protected1, protected2 and protected3, defined
+ in moda, are used in moda.
+ 2. Protected symbol, protected3, defined in modb, are used in modb
+ 3. Symbol, protected1, defined in modb, is used in main and modb.
+ 4. Symbol, protected2, defined in main, is used in main.
+ 5. Symbol, protected3, defined in modb, is also used in main.
+
+ 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/>. */
+
+/* This file must be compiled as PIE to avoid copy relocation when
+ accessing protected symbols defined in shared libaries since copy
+ relocation doesn't work with protected symbols and linker in
+ binutils 2.26 enforces this rule. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "tst-protected1mod.h"
+
+/* Prototype for our test function. */
+extern int do_test (void);
+
+int protected2 = -1;
+
+#define TEST_FUNCTION do_test ()
+
+/* This defines the `main' function and some more. */
+#include <test-skeleton.c>
+
+int
+do_test (void)
+{
+ int res = 0;
+
+ /* Check if we get the same address for the protected data symbol. */
+ if (&protected1 == protected1a_p ())
+ {
+ puts ("`protected1' in main and moda has same address");
+ res = 1;
+ }
+ if (&protected1 != protected1b_p ())
+ {
+ puts ("`protected1' in main and modb doesn't have same address");
+ res = 1;
+ }
+
+ /* Check if we get the right value for the protected data symbol. */
+ if (protected1 != -3)
+ {
+ puts ("`protected1' in main and modb doesn't have same value");
+ res = 1;
+ }
+
+ /* Check if we get the right value for data defined in executable. */
+ if (protected2 != -1)
+ {
+ puts ("`protected2' in main has the wrong value");
+ res = 1;
+ }
+
+ /* Check `protected1' in moda. */
+ if (!check_protected1 ())
+ {
+ puts ("`protected1' in moda has the wrong value");
+ res = 1;
+ }
+
+ /* Check `protected2' in moda. */
+ if (!check_protected2 ())
+ {
+ puts ("`protected2' in moda has the wrong value");
+ res = 1;
+ }
+
+ /* Check if we get the same address for the protected data symbol. */
+ if (&protected3 == protected3a_p ())
+ {
+ puts ("`protected3' in main and moda has same address");
+ res = 1;
+ }
+ if (&protected3 != protected3b_p ())
+ {
+ puts ("`protected3' in main and modb doesn't have same address");
+ res = 1;
+ }
+
+ /* Check if we get the right value for the protected data symbol. */
+ if (protected3 != -5)
+ {
+ puts ("`protected3' in main and modb doesn't have same value");
+ res = 1;
+ }
+
+ /* Check `protected3' in moda. */
+ if (!check_protected3a ())
+ {
+ puts ("`protected3' in moda has the wrong value");
+ res = 1;
+ }
+
+ /* Check `protected3' in modb. */
+ if (!check_protected3b ())
+ {
+ puts ("`protected3' in modb has the wrong value");
+ res = 1;
+ }
+
+ /* Set `protected2' in moda to 30. */
+ set_protected2 (300);
+
+ /* Check `protected2' in moda. */
+ if (!check_protected2 ())
+ {
+ puts ("`protected2' in moda has the wrong value");
+ res = 1;
+ }
+
+ /* Check if we get the right value for data defined in executable. */
+ if (protected2 != -1)
+ {
+ puts ("`protected2' in main has the wrong value");
+ res = 1;
+ }
+
+ /* Set `protected1' in moda to 30. */
+ set_protected1a (30);
+
+ /* Check `protected1' in moda. */
+ if (!check_protected1 ())
+ {
+ puts ("`protected1' in moda has the wrong value");
+ res = 1;
+ }
+
+ /* Check if we get the same value for the protected data symbol. */
+ if (protected1 != -3)
+ {
+ puts ("`protected1' in main has the wrong value");
+ res = 1;
+ }
+
+ protected2 = -300;
+
+ /* Check `protected2' in moda. */
+ if (!check_protected2 ())
+ {
+ puts ("`protected2' in moda has the wrong value");
+ res = 1;
+ }
+
+ /* Check if data defined in executable is changed. */
+ if (protected2 != -300)
+ {
+ puts ("`protected2' in main is changed");
+ res = 1;
+ }
+
+ /* Set `protected1' in modb to 40. */
+ set_protected1b (40);
+
+ /* Check `protected1' in moda. */
+ if (!check_protected1 ())
+ {
+ puts ("`protected1' in moda has the wrong value");
+ res = 1;
+ }
+
+ /* Check if we get the updated value for the protected data symbol. */
+ if (protected1 != 40)
+ {
+ puts ("`protected1' in main doesn't have the updated value");
+ res = 1;
+ }
+
+ /* Set `protected3' in moda to 80. */
+ set_protected3a (80);
+
+ /* Check `protected3' in moda. */
+ if (!check_protected3a ())
+ {
+ puts ("`protected3' in moda has the wrong value");
+ res = 1;
+ }
+
+ /* Check if we get the updated value for the protected data symbol. */
+ if (protected3 != -5)
+ {
+ puts ("`protected3' in main doesn't have the updated value");
+ res = 1;
+ }
+
+ /* Check `protected3' in modb. */
+ if (!check_protected3b ())
+ {
+ puts ("`protected3' in modb has the wrong value");
+ res = 1;
+ }
+
+ /* Set `protected3' in modb to 100. */
+ set_protected3b (100);
+
+ /* Check `protected3' in moda. */
+ if (!check_protected3a ())
+ {
+ puts ("`protected3' in moda has the wrong value");
+ res = 1;
+ }
+
+ /* Check if we get the updated value for the protected data symbol. */
+ if (protected3 != 100)
+ {
+ puts ("`protected3' in main doesn't have the updated value");
+ res = 1;
+ }
+
+ /* Check `protected3' in modb. */
+ if (!check_protected3b ())
+ {
+ puts ("`protected3' in modb has the wrong value");
+ res = 1;
+ }
+
+ return res;
+}
diff --git a/elf/tst-protected1mod.h b/elf/tst-protected1mod.h
new file mode 100644
index 0000000000..301e019dd8
--- /dev/null
+++ b/elf/tst-protected1mod.h
@@ -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/>. */
+
+/* Prototypes for the functions in the DSOs. */
+extern int protected1;
+extern int protected2;
+extern int protected3;
+
+extern void set_protected1a (int);
+extern void set_protected1b (int);
+extern int *protected1a_p (void);
+extern int *protected1b_p (void);
+
+extern void set_expected_protected1 (int);
+extern int check_protected1 (void);
+
+extern void set_protected2 (int);
+extern int check_protected2 (void);
+
+extern void set_expected_protected3a (int);
+extern void set_protected3a (int);
+extern int check_protected3a (void);
+extern int *protected3a_p (void);
+extern void set_expected_protected3b (int);
+extern void set_protected3b (int);
+extern int check_protected3b (void);
+extern int *protected3b_p (void);
diff --git a/elf/tst-protected1moda.c b/elf/tst-protected1moda.c
new file mode 100644
index 0000000000..720f474281
--- /dev/null
+++ b/elf/tst-protected1moda.c
@@ -0,0 +1,92 @@
+/* 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 "tst-protected1mod.h"
+
+int protected1 = 3;
+static int expected_protected1 = 3;
+int protected2 = 4;
+static int expected_protected2 = 4;
+int protected3 = 5;
+static int expected_protected3 = 5;
+
+asm (".protected protected1");
+asm (".protected protected2");
+asm (".protected protected3");
+
+void
+set_protected1a (int i)
+{
+ protected1 = i;
+ set_expected_protected1 (i);
+}
+
+void
+set_expected_protected1 (int i)
+{
+ expected_protected1 = i;
+}
+
+int *
+protected1a_p (void)
+{
+ return &protected1;
+}
+
+int
+check_protected1 (void)
+{
+ return protected1 == expected_protected1;
+}
+
+void
+set_protected2 (int i)
+{
+ protected2 = i;
+ expected_protected2 = i;
+}
+
+int
+check_protected2 (void)
+{
+ return protected2 == expected_protected2;
+}
+
+void
+set_expected_protected3a (int i)
+{
+ expected_protected3 = i;
+}
+
+void
+set_protected3a (int i)
+{
+ protected3 = i;
+ set_expected_protected3a (i);
+}
+
+int
+check_protected3a (void)
+{
+ return protected3 == expected_protected3;
+}
+
+int *
+protected3a_p (void)
+{
+ return &protected3;
+}
diff --git a/elf/tst-protected1modb.c b/elf/tst-protected1modb.c
new file mode 100644
index 0000000000..ddfa646ec3
--- /dev/null
+++ b/elf/tst-protected1modb.c
@@ -0,0 +1,62 @@
+/* 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 <stdlib.h>
+#include "tst-protected1mod.h"
+
+int protected1 = -3;
+int protected3 = -5;
+static int expected_protected3 = -5;
+
+asm (".protected protected3");
+
+void
+set_protected1b (int i)
+{
+ protected1 = i;
+}
+
+int *
+protected1b_p (void)
+{
+ return &protected1;
+}
+
+void
+set_expected_protected3b (int i)
+{
+ expected_protected3 = i;
+}
+
+void
+set_protected3b (int i)
+{
+ protected3 = i;
+ set_expected_protected3b (i);
+}
+
+int
+check_protected3b (void)
+{
+ return protected3 == expected_protected3;
+}
+
+int *
+protected3b_p (void)
+{
+ return &protected3;
+}
diff --git a/elf/tst-ptrguard1.c b/elf/tst-ptrguard1.c
index c9236b94a7..55fda84f42 100644
--- a/elf/tst-ptrguard1.c
+++ b/elf/tst-ptrguard1.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2013-2014 Free Software Foundation, Inc.
+/* Copyright (C) 2013-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
diff --git a/elf/tst-rtld-load-self.sh b/elf/tst-rtld-load-self.sh
index f6e007c201..45789a8f06 100755
--- a/elf/tst-rtld-load-self.sh
+++ b/elf/tst-rtld-load-self.sh
@@ -1,6 +1,6 @@
#! /bin/sh
# Test how rtld loads itself.
-# Copyright (C) 2012-2014 Free Software Foundation, Inc.
+# Copyright (C) 2012-2015 Free Software Foundation, Inc.
# This file is part of the GNU C Library.
#
diff --git a/elf/tst-stackguard1.c b/elf/tst-stackguard1.c
index f704260934..69ef09fb89 100644
--- a/elf/tst-stackguard1.c
+++ b/elf/tst-stackguard1.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2005-2014 Free Software Foundation, Inc.
+/* Copyright (C) 2005-2015 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Jakub Jelinek <jakub@redhat.com>, 2005.
diff --git a/elf/tst-tls10.c b/elf/tst-tls10.c
index 347243f66b..eb1ecb9216 100644
--- a/elf/tst-tls10.c
+++ b/elf/tst-tls10.c
@@ -8,8 +8,8 @@ __thread struct A local = { 1, 2, 3 };
if (p->a != S || p->b != S + 1 || p->c != S + 2) \
abort ()
-int
-main (void)
+static int
+do_test (void)
{
struct A *p;
if (local.a != 1 || local.b != 2 || local.c != 3)
@@ -35,3 +35,6 @@ main (void)
exit (0);
}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/elf/tst-tls11.c b/elf/tst-tls11.c
index 8a2fef4a7f..8ceac14168 100644
--- a/elf/tst-tls11.c
+++ b/elf/tst-tls11.c
@@ -5,8 +5,8 @@
if (p->a != S || p->b != S + 1 || p->c != S + 2) \
abort ()
-int
-main (void)
+static int
+do_test (void)
{
struct A *p;
check1 ();
@@ -24,3 +24,6 @@ main (void)
exit (0);
}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/elf/tst-tls12.c b/elf/tst-tls12.c
index 9086d17176..8093894b93 100644
--- a/elf/tst-tls12.c
+++ b/elf/tst-tls12.c
@@ -5,8 +5,8 @@
if (p->a != S || p->b != S + 1 || p->c != S + 2) \
abort ()
-int
-main (void)
+static int
+do_test (void)
{
struct A *p;
check1 ();
@@ -15,3 +15,6 @@ main (void)
exit (0);
}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/elf/tst-tlsalign-extern-static.c b/elf/tst-tlsalign-extern-static.c
new file mode 100644
index 0000000000..e84900eee4
--- /dev/null
+++ b/elf/tst-tlsalign-extern-static.c
@@ -0,0 +1 @@
+#include "tst-tlsalign-extern.c"
diff --git a/elf/tst-tlsalign-extern.c b/elf/tst-tlsalign-extern.c
new file mode 100644
index 0000000000..661b6712e3
--- /dev/null
+++ b/elf/tst-tlsalign-extern.c
@@ -0,0 +1,74 @@
+/* Test for large alignment in TLS blocks (extern case), BZ#18383.
+ 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 <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+/* This is the same as tst-tlsalign-static.c, except that it uses
+ TLS variables that are defined in a separate translation unit
+ (ts-tlsalign-vars.c). It turned out that the cause of BZ#18383
+ on ARM was actually an ARM assembler bug triggered by the ways of
+ using .tdata/.tbss sections and relocs referring to them that GCC
+ chooses when the variables are defined in the same translation
+ unit that contains the references. */
+
+extern __thread int tdata1;
+extern __thread int tdata2;
+extern __thread int tdata3;
+extern __thread int tbss1;
+extern __thread int tbss2;
+extern __thread int tbss3;
+
+static int
+test_one (const char *which, unsigned int alignment, int *var, int value)
+{
+ uintptr_t addr = (uintptr_t) var;
+ unsigned int misalign = addr & (alignment - 1);
+
+ printf ("%s TLS address %p %% %u = %u\n",
+ which, (void *) var, alignment, misalign);
+
+ int got = *var;
+ if (got != value)
+ {
+ printf ("%s value %d should be %d\n", which, got, value);
+ return 1;
+ }
+
+ return misalign != 0;
+}
+
+static int
+do_test (void)
+{
+ int fail = 0;
+
+ fail |= test_one ("tdata1", 4, &tdata1, 1);
+ fail |= test_one ("tdata2", 0x10, &tdata2, 2);
+ fail |= test_one ("tdata3", 0x1000, &tdata3, 4);
+
+ fail |= test_one ("tbss1", 4, &tbss1, 0);
+ fail |= test_one ("tbss2", 0x10, &tbss2, 0);
+ fail |= test_one ("tbss3", 0x1000, &tbss3, 0);
+
+ return fail ? EXIT_FAILURE : EXIT_SUCCESS;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/elf/tst-tlsalign-lib.c b/elf/tst-tlsalign-lib.c
new file mode 100644
index 0000000000..4371e581a6
--- /dev/null
+++ b/elf/tst-tlsalign-lib.c
@@ -0,0 +1,6 @@
+__thread int mod_tdata1 = 1;
+__thread int mod_tdata2 __attribute__ ((aligned (0x10))) = 2;
+__thread int mod_tdata3 __attribute__ ((aligned (0x1000))) = 4;
+__thread int mod_tbss1;
+__thread int mod_tbss2 __attribute__ ((aligned (0x10)));
+__thread int mod_tbss3 __attribute__ ((aligned (0x1000)));
diff --git a/elf/tst-tlsalign-static.c b/elf/tst-tlsalign-static.c
new file mode 100644
index 0000000000..1671abf28e
--- /dev/null
+++ b/elf/tst-tlsalign-static.c
@@ -0,0 +1,2 @@
+#define NO_LIB
+#include "tst-tlsalign.c"
diff --git a/elf/tst-tlsalign-vars.c b/elf/tst-tlsalign-vars.c
new file mode 100644
index 0000000000..01b3501d3b
--- /dev/null
+++ b/elf/tst-tlsalign-vars.c
@@ -0,0 +1,28 @@
+/* This is for tst-tlsalign-extern.c, which see. It's essential for the
+ purpose of the test that these definitions be in a separate translation
+ unit from the code using the variables. */
+
+__thread int tdata1 = 1;
+__thread int tdata2 __attribute__ ((aligned (0x10))) = 2;
+__thread int tdata3 __attribute__ ((aligned (0x1000))) = 4;
+__thread int tbss1;
+__thread int tbss2 __attribute__ ((aligned (0x10)));
+__thread int tbss3 __attribute__ ((aligned (0x1000)));
+
+/* This function is never called. But its presence in this translation
+ unit makes GCC emit the variables above in the order defined (perhaps
+ because it's the order in which they're used here?) rather than
+ reordering them into descending order of alignment requirement--and so
+ keeps it more similar to the tst-tlsalign-static.c case--just in case
+ that affects the bug (though there is no evidence that it does). */
+
+void
+unused (void)
+{
+ tdata1 = -1;
+ tdata2 = -2;
+ tdata3 = -3;
+ tbss1 = -4;
+ tbss2 = -5;
+ tbss3 = -6;
+}
diff --git a/elf/tst-tlsalign.c b/elf/tst-tlsalign.c
new file mode 100644
index 0000000000..da04f577e2
--- /dev/null
+++ b/elf/tst-tlsalign.c
@@ -0,0 +1,85 @@
+/* Test for large alignment in TLS blocks, BZ#18383.
+ 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 <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+static __thread int tdata1 = 1;
+static __thread int tdata2 __attribute__ ((aligned (0x10))) = 2;
+static __thread int tdata3 __attribute__ ((aligned (0x1000))) = 4;
+static __thread int tbss1;
+static __thread int tbss2 __attribute__ ((aligned (0x10)));
+static __thread int tbss3 __attribute__ ((aligned (0x1000)));
+
+#ifndef NO_LIB
+extern __thread int mod_tdata1;
+extern __thread int mod_tdata2;
+extern __thread int mod_tdata3;
+extern __thread int mod_tbss1;
+extern __thread int mod_tbss2;
+extern __thread int mod_tbss3;
+#endif
+
+static int
+test_one (const char *which, unsigned int alignment, int *var, int value)
+{
+ uintptr_t addr = (uintptr_t) var;
+ unsigned int misalign = addr & (alignment - 1);
+
+ printf ("%s TLS address %p %% %u = %u\n",
+ which, (void *) var, alignment, misalign);
+
+ int got = *var;
+ if (got != value)
+ {
+ printf ("%s value %d should be %d\n", which, got, value);
+ return 1;
+ }
+
+ return misalign != 0;
+}
+
+static int
+do_test (void)
+{
+ int fail = 0;
+
+ fail |= test_one ("tdata1", 4, &tdata1, 1);
+ fail |= test_one ("tdata2", 0x10, &tdata2, 2);
+ fail |= test_one ("tdata3", 0x1000, &tdata3, 4);
+
+ fail |= test_one ("tbss1", 4, &tbss1, 0);
+ fail |= test_one ("tbss2", 0x10, &tbss2, 0);
+ fail |= test_one ("tbss3", 0x1000, &tbss3, 0);
+
+#ifndef NO_LIB
+ fail |= test_one ("mod_tdata1", 4, &mod_tdata1, 1);
+ fail |= test_one ("mod_tdata2", 0x10, &mod_tdata2, 2);
+ fail |= test_one ("mod_tdata3", 0x1000, &mod_tdata3, 4);
+
+ fail |= test_one ("mod_tbss1", 4, &mod_tbss1, 0);
+ fail |= test_one ("mod_tbss2", 0x10, &mod_tbss2, 0);
+ fail |= test_one ("mod_tbss3", 0x1000, &mod_tbss3, 0);
+#endif
+
+ return fail ? EXIT_FAILURE : EXIT_SUCCESS;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/elf/tst-unique4lib.cc b/elf/tst-unique4lib.cc
index c9fdf9cfea..17a7cdf567 100644
--- a/elf/tst-unique4lib.cc
+++ b/elf/tst-unique4lib.cc
@@ -6,7 +6,7 @@ int S<N>::i = N;
template<int N>
const int S<N>::j __attribute__ ((used)) = -1;
-static int a[24] =
+static int a[24] __attribute__ ((used)) =
{
S<1>::i, S<2>::i, S<3>::i, S<4>::i, S<5>::i, S<6>::i, S<7>::i, S<8>::i,
S<9>::i, S<10>::i, S<11>::i, S<12>::i, S<13>::i, S<14>::i, S<15>::i,
@@ -14,4 +14,4 @@ static int a[24] =
S<23>::i, S<24>::i
};
-static int b = S<1>::j;
+static int b __attribute__ ((used)) = S<1>::j;
diff --git a/elf/tst-znodelete-zlib.cc b/elf/tst-znodelete-zlib.cc
new file mode 100644
index 0000000000..1e8f3686d7
--- /dev/null
+++ b/elf/tst-znodelete-zlib.cc
@@ -0,0 +1,6 @@
+extern int not_exist (void);
+
+int foo (void)
+{
+ return not_exist ();
+}
diff --git a/elf/vismain.c b/elf/vismain.c
index f91428b8a8..05b374812c 100644
--- a/elf/vismain.c
+++ b/elf/vismain.c
@@ -1,4 +1,4 @@
-/* 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.
The GNU C Library is free software; you can redistribute it and/or
@@ -15,6 +15,11 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
+/* This file must be compiled as PIE to avoid copy relocation when
+ accessing protected symbols defined in shared libaries since copy
+ relocation doesn't work with protected symbols and linker in
+ binutils 2.26 enforces this rule. */
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
diff --git a/elf/vismod1.c b/elf/vismod1.c
index 06e0ba5a2b..92a07f96fd 100644
--- a/elf/vismod1.c
+++ b/elf/vismod1.c
@@ -1,4 +1,4 @@
-/* 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.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/elf/vismod2.c b/elf/vismod2.c
index 8f9adee979..8c53b05077 100644
--- a/elf/vismod2.c
+++ b/elf/vismod2.c
@@ -1,4 +1,4 @@
-/* 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.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/elf/vismod3.c b/elf/vismod3.c
index e312ad5317..3e7fda8987 100644
--- a/elf/vismod3.c
+++ b/elf/vismod3.c
@@ -1,4 +1,4 @@
-/* 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.
The GNU C Library is free software; you can redistribute it and/or