diff options
Diffstat (limited to 'elf')
461 files changed, 0 insertions, 43439 deletions
diff --git a/elf/Makefile b/elf/Makefile deleted file mode 100644 index 201b328f88..0000000000 --- a/elf/Makefile +++ /dev/null @@ -1,1412 +0,0 @@ -# Copyright (C) 1995-2017 Free Software Foundation, Inc. -# This file is part of the GNU C Library. - -# The GNU C Library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. - -# The GNU C Library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. - -# You should have received a copy of the GNU Lesser General Public -# License along with the GNU C Library; if not, see -# <http://www.gnu.org/licenses/>. - -# Makefile for elf subdirectory of GNU C Library. - -subdir := elf - -include ../Makeconfig - -headers = elf.h bits/elfclass.h link.h bits/link.h -routines = $(all-dl-routines) dl-support dl-iteratephdr \ - dl-addr dl-addr-obj enbl-secure dl-profstub \ - dl-origin dl-libc dl-sym dl-sysdep dl-error - -# The core dynamic linking functions are in libc for the static and -# profiled libraries. -dl-routines = $(addprefix dl-,load lookup object reloc deps hwcaps \ - runtime init fini debug misc \ - version profile conflict tls origin scope \ - execstack caller open close trampoline) -ifeq (yes,$(use-ldconfig)) -dl-routines += dl-cache -endif - -ifneq (no,$(have-tunables)) -dl-routines += dl-tunables -tunables-type = $(addprefix TUNABLES_FRONTEND_,$(have-tunables)) -CPPFLAGS-dl-tunables.c = -DTUNABLES_FRONTEND=$(tunables-type) - -# Make sure that the compiler does not insert any library calls in tunables -# code paths. -ifeq (yes,$(have-loop-to-function)) -CFLAGS-dl-tunables.c = -fno-tree-loop-distribute-patterns -endif -endif - -all-dl-routines = $(dl-routines) $(sysdep-dl-routines) -# But they are absent from the shared libc, because that code is in ld.so. -elide-routines.os = $(all-dl-routines) dl-support enbl-secure dl-origin \ - dl-sysdep -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 $(all-dl-routines) dl-sysdep dl-environ dl-minimal \ - dl-error-minimal -all-rtld-routines = $(rtld-routines) $(sysdep-rtld-routines) - -CFLAGS-dl-runtime.c = -fexceptions -fasynchronous-unwind-tables -CFLAGS-dl-lookup.c = -fexceptions -fasynchronous-unwind-tables -CFLAGS-dl-iterate-phdr.c = $(uses-callbacks) - -# Compile rtld itself without stack protection. -# Also compile all routines in the static library that are elided from -# the shared libc because they are in libc.a in the same way. - -define elide-stack-protector -$(if $(filter $(@F),$(patsubst %,%$(1),$(2))), $(no-stack-protector)) -endef - -CFLAGS-.o += $(call elide-stack-protector,.o,$(elide-routines.os)) -CFLAGS-.op += $(call elide-stack-protector,.op,$(elide-routines.os)) -CFLAGS-.os += $(call elide-stack-protector,.os,$(all-rtld-routines)) - -ifeq ($(unwind-find-fde),yes) -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 - -ifeq ($(build-shared),yes) -ld-map = $(common-objpfx)ld.map -endif - -ifeq (yes,$(build-shared)) -extra-objs = $(all-rtld-routines:%=%.os) soinit.os sofini.os interp.os -generated += librtld.os dl-allobjs.os ld.so ldd -install-others = $(inst_rtlddir)/$(rtld-installed-name) -install-bin-script = ldd -endif - -others = sprof sln -install-bin = sprof -others-static = sln -install-rootsbin = sln -sln-modules := static-stubs -extra-objs += $(sln-modules:=.o) - -ifeq (yes,$(use-ldconfig)) -ifeq (yes,$(build-shared)) -others-static += ldconfig -others += ldconfig -install-rootsbin += ldconfig - -ldconfig-modules := cache readlib xmalloc xstrdup chroot_canon static-stubs -extra-objs += $(ldconfig-modules:=.o) -endif -endif - -# To find xmalloc.c and xstrdup.c -vpath %.c ../locale/programs - -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 -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.sh $(common-objpfx)config.make - sed -e 's%@BASH@%$(BASH)%g' \ - -e 's%@VERSION@%$(version)%g' \ - -e 's%@TEXTDOMAINDIR@%$(localedir)%g' \ - -e 's%@PREFIX@%$(prefix)%g' \ - -e 's|@PKGVERSION@|$(PKGVERSION)|g' \ - -e 's|@REPORT_BUGS_TO@|$(REPORT_BUGS_TO)|g' \ - < $< > $@.new - chmod 555 $@.new - mv -f $@.new $@ -$(inst_auditdir)/sotruss-lib.so: $(objpfx)sotruss-lib.so $(+force) - $(do-install-program) -endif - -tests-static-normal := tst-leaks1-static tst-array1-static tst-array5-static \ - tst-dl-iter-static \ - tst-tlsalign-static tst-tlsalign-extern-static \ - tst-linkall-static tst-env-setuid tst-env-setuid-tunables -tests-static-internal := tst-tls1-static tst-tls2-static \ - tst-ptrguard1-static tst-stackguard1-static - -tests := tst-tls9 tst-leaks1 \ - tst-array1 tst-array2 tst-array3 tst-array4 tst-array5 \ - tst-auxv -tests-internal := tst-tls1 tst-tls2 $(tests-static-internal) -tests-static := $(tests-static-normal) $(tests-static-internal) - -ifeq (yes,$(build-shared)) -tests-static += tst-tls9-static -tst-tls9-static-ENV = \ - LD_LIBRARY_PATH=$(objpfx):$(common-objpfx):$(common-objpfx)dlfcn - -tests += restest1 preloadtest loadfail multiload origtest resolvfail \ - constload1 order noload filter \ - reldep reldep2 reldep3 reldep4 nodelete nodelete2 \ - nodlopen nodlopen2 lateglobal initfirst global \ - restest2 next dblload dblunload reldep5 reldep6 reldep7 reldep8 \ - tst-tls4 tst-tls5 \ - tst-tls10 tst-tls11 tst-tls12 tst-tls13 tst-tls14 tst-tls15 \ - tst-tls16 tst-tls17 tst-tls18 tst-tls19 tst-tls-dlinfo \ - tst-align tst-align2 $(tests-execstack-$(have-z-execstack)) \ - tst-dlmodcount tst-dlopenrpath tst-deep1 \ - tst-dlmopen1 tst-dlmopen3 \ - unload3 unload4 unload5 unload6 unload7 unload8 tst-global1 order2 \ - tst-audit1 tst-audit2 tst-audit8 tst-audit9 \ - tst-addr1 tst-thrlock \ - tst-unique1 tst-unique2 $(if $(CXX),tst-unique3 tst-unique4 \ - tst-nodelete) \ - tst-initorder tst-initorder2 tst-relsort1 tst-null-argv \ - tst-tlsalign tst-tlsalign-extern tst-nodelete-opened \ - tst-nodelete2 tst-audit11 tst-audit12 tst-dlsym-error tst-noload \ - tst-latepthread tst-tls-manydynamic tst-nodelete-dlclose -# reldep9 -tests-internal += loadtest unload unload2 circleload1 \ - neededtest neededtest2 neededtest3 neededtest4 \ - tst-tls3 tst-tls6 tst-tls7 tst-tls8 tst-dlmopen2 \ - tst-ptrguard1 tst-stackguard1 -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) -tests-execstack-yes = tst-execstack tst-execstack-needed tst-execstack-prog -endif -endif -ifeq ($(run-built-tests),yes) -tests-special += $(objpfx)tst-leaks1-mem.out \ - $(objpfx)tst-leaks1-static-mem.out $(objpfx)noload-mem.out \ - $(objpfx)tst-ldconfig-X.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 -tlsmod17a-modules = $(addprefix tst-tlsmod17a, $(tlsmod17a-suffixes)) -tlsmod18a-modules = $(addprefix tst-tlsmod18a, $(tlsmod17a-suffixes)) -one-hundred = $(foreach x,0 1 2 3 4 5 6 7 8 9, \ - 0$x 1$x 2$x 3$x 4$x 5$x 6$x 7$x 8$x 9$x) -tst-tls-many-dynamic-modules := \ - $(foreach n,$(one-hundred),tst-tls-manydynamic$(n)mod) -extra-test-objs += $(tlsmod17a-modules:=.os) $(tlsmod18a-modules:=.os) \ - tst-tlsalign-vars.o -test-extras += tst-tlsmod17a tst-tlsmod18a tst-tlsalign-vars -modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \ - testobj1_1 failobj constload2 constload3 unloadmod \ - dep1 dep2 dep3 dep4 vismod1 vismod2 vismod3 \ - nodelmod1 nodelmod2 nodelmod3 nodelmod4 \ - nodel2mod1 nodel2mod2 nodel2mod3 \ - nodlopenmod nodlopenmod2 filtmod1 filtmod2 \ - reldepmod1 reldepmod2 reldepmod3 reldepmod4 nextmod1 nextmod2 \ - reldep4mod1 reldep4mod2 reldep4mod3 reldep4mod4 \ - neededobj1 neededobj2 neededobj3 neededobj4 \ - neededobj5 neededobj6 firstobj globalmod1 \ - unload2mod unload2dep ltglobmod1 ltglobmod2 pathoptobj \ - dblloadmod1 dblloadmod2 dblloadmod3 reldepmod5 reldepmod6 \ - reldep6mod0 reldep6mod1 reldep6mod2 reldep6mod3 reldep6mod4 \ - reldep7mod1 reldep7mod2 \ - tst-tlsmod1 tst-tlsmod2 tst-tlsmod3 tst-tlsmod4 \ - tst-tlsmod5 tst-tlsmod6 tst-tlsmod7 tst-tlsmod8 \ - tst-tlsmod9 tst-tlsmod10 tst-tlsmod11 tst-tlsmod12 \ - tst-tlsmod13 tst-tlsmod13a tst-tlsmod14a tst-tlsmod14b \ - tst-tlsmod15a tst-tlsmod15b tst-tlsmod16a tst-tlsmod16b \ - $(tlsmod17a-modules) tst-tlsmod17b $(tlsmod18a-modules) \ - tst-tls19mod1 tst-tls19mod2 tst-tls19mod3 \ - circlemod1 circlemod1a circlemod2 circlemod2a \ - circlemod3 circlemod3a \ - reldep8mod1 reldep8mod2 reldep8mod3 \ - reldep9mod1 reldep9mod2 reldep9mod3 \ - tst-alignmod tst-alignmod2 \ - $(modules-execstack-$(have-z-execstack)) \ - tst-dlopenrpathmod tst-deep1mod1 tst-deep1mod2 tst-deep1mod3 \ - tst-dlmopen1mod tst-auditmod1 \ - unload3mod1 unload3mod2 unload3mod3 unload3mod4 \ - unload4mod1 unload4mod2 unload4mod3 unload4mod4 \ - unload6mod1 unload6mod2 unload6mod3 \ - unload7mod1 unload7mod2 \ - unload8mod1 unload8mod1x unload8mod2 unload8mod3 \ - order2mod1 order2mod2 order2mod3 order2mod4 \ - tst-unique1mod1 tst-unique1mod2 \ - tst-unique2mod1 tst-unique2mod2 \ - 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-tlsalign-lib tst-nodelete-opened-lib tst-nodelete2mod \ - tst-audit11mod1 tst-audit11mod2 tst-auditmod11 \ - tst-audit12mod1 tst-audit12mod2 tst-audit12mod3 tst-auditmod12 \ - tst-latepthreadmod $(tst-tls-many-dynamic-modules) \ - tst-nodelete-dlclose-dso tst-nodelete-dlclose-plugin -ifeq (yes,$(have-mtls-dialect-gnu2)) -tests += tst-gnu2-tls1 -modules-names += tst-gnu2-tls1mod -$(objpfx)tst-gnu2-tls1: $(objpfx)tst-gnu2-tls1mod.so -tst-gnu2-tls1mod.so-no-z-defs = yes -CFLAGS-tst-gnu2-tls1mod.c += -mtls-dialect=gnu2 -endif -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 -# These tests fail with GCC versions prior to 5.1 and with some versions -# of binutils. See https://sourceware.org/bugzilla/show_bug.cgi?id=17709 -# and https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65248 for details. -# Perhaps in future we can make these XFAILs conditional on some detection -# of compiler/linker behavior/version. -test-xfail-tst-protected1a = yes -test-xfail-tst-protected1b = yes -endif -ifeq (yesyes,$(have-fpie)$(build-shared)) -modules-names += tst-piemod1 -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))) - -# filtmod1.so has a special rule -modules-names-nobuild := filtmod1 - -tests += $(tests-static) - -ifneq (no,$(multi-arch)) -tests-ifuncstatic := ifuncmain1static ifuncmain1picstatic \ - ifuncmain2static ifuncmain2picstatic \ - ifuncmain4static ifuncmain4picstatic \ - ifuncmain5static ifuncmain5picstatic \ - ifuncmain7static ifuncmain7picstatic -tests-static += $(tests-ifuncstatic) -tests-internal += $(tests-ifuncstatic) -ifeq (yes,$(build-shared)) -tests-internal += \ - ifuncmain1 ifuncmain1pic ifuncmain1vis ifuncmain1vispic \ - ifuncmain1staticpic \ - ifuncmain2 ifuncmain2pic ifuncmain3 ifuncmain4 \ - ifuncmain5 ifuncmain5pic ifuncmain5staticpic \ - ifuncmain7 ifuncmain7pic -ifunc-test-modules = ifuncdep1 ifuncdep1pic ifuncdep2 ifuncdep2pic \ - ifuncdep5 ifuncdep5pic -extra-test-objs += $(ifunc-test-modules:=.o) -test-internal-extras += $(ifunc-test-modules) -ifeq (yes,$(have-fpie)) -ifunc-pie-tests = ifuncmain1pie ifuncmain1vispie ifuncmain1staticpie \ - ifuncmain5pie ifuncmain6pie ifuncmain7pie -tests-internal += $(ifunc-pie-tests) -tests-pie += $(ifunc-pie-tests) -endif -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 - -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: $(objpfx)check-abi-ld.out -tests-special += $(objpfx)check-abi-ld.out -update-abi: update-abi-ld -update-all-abi: update-all-abi-ld - -ifeq ($(have-glob-dat-reloc),yes) -tests += tst-prelink -ifeq ($(run-built-tests),yes) -tests-special += $(objpfx)tst-prelink-cmp.out -endif -endif - -# The test requires shared _and_ PIE because the executable -# unit test driver must be able to link with the shared object -# that is going to eventually go into an installed DSO. -ifeq (yesyes,$(have-fpie)$(build-shared)) -tests-internal += tst-_dl_addr_inside_object -tests-pie += tst-_dl_addr_inside_object -$(objpfx)tst-_dl_addr_inside_object: $(objpfx)dl-addr-obj.os -CFLAGS-tst-_dl_addr_inside_object.c += $(PIE-ccflag) -endif - -# By default tst-linkall-static should try to use crypt routines to test -# static libcrypt use. -CFLAGS-tst-linkall-static.c = -DUSE_CRYPT=1 -# However, if we are using NSS crypto and we don't have a static -# library, then we exclude the use of crypt functions in the test. -# We similarly exclude libcrypt.a from the static link (see below). -ifeq (yesno,$(nss-crypt)$(static-nss-crypt)) -CFLAGS-tst-linkall-static.c = -DUSE_CRYPT=0 -endif - -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. -lib-noranlib: $(objpfx)$(rtld-installed-name) \ - $(addprefix $(objpfx),$(extra-objs)) -endif - -# Command to link into a larger single relocatable object. -reloc-link = $(LINK.o) -nostdlib -nostartfiles -r - -$(objpfx)sotruss-lib.so: $(shlib-lds) - -$(objpfx)dl-allobjs.os: $(all-rtld-routines:%=$(objpfx)%.os) - $(reloc-link) -o $@ $^ - -# Link together the dynamic linker into a single relocatable object. -# First we do a link against libc_pic.a just to get a link map, -# and discard the object produced by that link. From the link map -# we can glean all the libc modules that need to go into the dynamic -# linker. Then we do a recursive make that goes into all the subdirs -# those modules come from and builds special rtld-foo.os versions that -# are compiled with special flags, and puts these modules into rtld-libc.a -# for us. Then we do the real link using rtld-libc.a instead of libc_pic.a. - -# If the compiler can do SSP, build the mapfile with dummy __stack_chk_fail -# and __stack_chk_fail_local symbols defined, to prevent the real things -# being dragged into rtld even though rtld is never built with stack- -# protection. - -ifeq ($(have-ssp),yes) -dummy-stack-chk-fail := -Wl,--defsym='__stack_chk_fail=0' \ - -Wl,--defsym='__stack_chk_fail_local=0' -else -dummy-stack-chk-fail := -endif - -$(objpfx)librtld.map: $(objpfx)dl-allobjs.os $(common-objpfx)libc_pic.a - @-rm -f $@T - $(reloc-link) -o $@.o $(dummy-stack-chk-fail) \ - '-Wl,-(' $^ -lgcc '-Wl,-)' -Wl,-Map,$@T - rm -f $@.o - mv -f $@T $@ - -$(objpfx)librtld.mk: $(objpfx)librtld.map Makefile - LC_ALL=C \ - sed -n 's@^$(common-objpfx)\([^(]*\)(\([^)]*\.os\)) *.*$$@\1 \2@p' \ - $< | \ - while read lib file; do \ - case $$lib in \ - libc_pic.a) \ - LC_ALL=C fgrep -l /$$file \ - $(common-objpfx)stamp.os $(common-objpfx)*/stamp.os | \ - LC_ALL=C \ - sed 's@^$(common-objpfx)\([^/]*\)/stamp\.os$$@rtld-\1'" +=$$file@"\ - ;; \ - */*.a) \ - echo rtld-$${lib%%/*} += $$file ;; \ - *) echo "Wasn't expecting $$lib($$file)" >&2; exit 1 ;; \ - esac; \ - done > $@T - echo rtld-subdirs = `LC_ALL=C sed 's/^rtld-\([^ ]*\).*$$/\1/' $@T \ - | LC_ALL=C sort -u` >> $@T - mv -f $@T $@ - -$(objpfx)rtld-libc.a: $(objpfx)librtld.mk FORCE - $(MAKE) -f $< -f rtld-Rules - -$(objpfx)librtld.os: $(objpfx)dl-allobjs.os $(objpfx)rtld-libc.a - $(LINK.o) -nostdlib -nostartfiles -r -o $@ '-Wl,-(' $^ -lgcc '-Wl,-)' \ - -Wl,-Map,$@.map - -generated += librtld.map librtld.mk rtld-libc.a librtld.os.map - -z-now-yes = -Wl,-z,now - -$(objpfx)ld.so: $(objpfx)librtld.os $(ld-map) -# Link into a temporary file so that we don't touch $@ at all -# if the sanity check below fails. - $(LINK.o) -nostdlib -nostartfiles -shared -o $@.new \ - $(LDFLAGS-rtld) -Wl,-z,defs $(z-now-$(bind-now)) \ - $(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 $@ - -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 - $(make-link) -generated += $(rtld-installed-name) -endif - -# Build a file mentioning all trustworthy directories to look for shared -# libraries when using LD_LIBRARY_PATH in a setuid program. The user can -# add directories to the list by defining $(user-defined-trusted-dirs) -# before starting make. -$(objpfx)trusted-dirs.h: $(objpfx)trusted-dirs.st; @: -$(objpfx)trusted-dirs.st: Makefile $(..)Makeconfig - $(make-target-directory) - echo "$(subst :, ,$(default-rpath) $(user-defined-trusted-dirs))" \ - | $(AWK) -f gen-trusted-dirs.awk > ${@:st=T}; - echo '#define DL_DST_LIB "$(notdir $(slibdir))"' >> ${@:st=T} - $(move-if-change) ${@:st=T} ${@:st=h} - touch $@ -CPPFLAGS-dl-load.c = -I$(objpfx). -I$(csu-objpfx). - -ifeq (yes,$(build-shared)) -$(inst_slibdir)/$(rtld-version-installed-name): $(objpfx)ld.so $(+force) - $(make-target-directory) - $(do-install-program) - -$(inst_rtlddir)/$(rtld-installed-name): \ - $(inst_slibdir)/$(rtld-version-installed-name) \ - $(inst_slibdir)/libc-$(version).so - $(make-target-directory) - $(make-shlib-link) - -# Special target called by parent to install just the dynamic linker. -.PHONY: ldso_install -ldso_install: $(inst_rtlddir)/$(rtld-installed-name) -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@%$(localedir)%g' - -ifeq ($(ldd-rewrite-script),no) -define gen-ldd -LC_ALL=C sed $(ldd-rewrite) < $< > $@.new -endef -else -define gen-ldd -LC_ALL=C sed $(ldd-rewrite) < $< \ -| LC_ALL=C sed -f $(patsubst $(..)/%,/%,$(..)$(ldd-rewrite-script)) > $@.new -endef -endif - -$(objpfx)ldd: ldd.bash.in $(common-objpfx)soversions.mk \ - $(common-objpfx)config.make - $(gen-ldd) - chmod 555 $@.new - mv -f $@.new $@ - -$(objpfx)sprof: $(libdl) - -$(objpfx)sln: $(sln-modules:%=$(objpfx)%.o) - -$(objpfx)ldconfig: $(ldconfig-modules:%=$(objpfx)%.o) - -SYSCONF-FLAGS := -D'SYSCONFDIR="$(sysconfdir)"' -CFLAGS-ldconfig.c = $(SYSCONF-FLAGS) -D'LIBDIR="$(libdir)"' \ - -D'SLIBDIR="$(slibdir)"' -libof-ldconfig = ldconfig -CFLAGS-dl-cache.c = $(SYSCONF-FLAGS) -CFLAGS-cache.c = $(SYSCONF-FLAGS) -CFLAGS-rtld.c = $(SYSCONF-FLAGS) - -cpp-srcs-left := $(all-rtld-routines:=.os) -lib := rtld -include $(patsubst %,$(..)libof-iterator.mk,$(cpp-srcs-left)) - -test-modules = $(addprefix $(objpfx),$(addsuffix .so,$(strip $(modules-names)))) -generated += $(addsuffix .so,$(strip $(modules-names))) - -$(objpfx)testobj1.so: $(libdl) -$(objpfx)testobj1_1.so: $(objpfx)testobj1.so $(libdl) -$(objpfx)testobj2.so: $(objpfx)testobj1.so $(libdl) -$(objpfx)testobj3.so: $(libdl) -$(objpfx)testobj4.so: $(libdl) -$(objpfx)testobj5.so: $(libdl) -$(objpfx)testobj6.so: $(objpfx)testobj1.so $(objpfx)testobj2.so $(libdl) -$(objpfx)failobj.so: $(objpfx)testobj6.so -$(objpfx)dep1.so: $(objpfx)dep2.so $(objpfx)dep4.so -$(objpfx)dep2.so: $(objpfx)dep3.so $(objpfx)dep4.so -$(objpfx)dep4.so: $(objpfx)dep3.so -$(objpfx)nodelmod3.so: $(objpfx)nodelmod4.so -$(objpfx)nextmod1.so: $(libdl) -$(objpfx)neededobj1.so: $(libdl) -$(objpfx)neededobj2.so: $(objpfx)neededobj1.so $(libdl) -$(objpfx)neededobj3.so: $(objpfx)neededobj1.so $(objpfx)neededobj2.so $(libdl) -$(objpfx)neededobj4.so: $(objpfx)neededobj1.so $(objpfx)neededobj2.so \ - $(objpfx)neededobj3.so $(libdl) -$(objpfx)neededobj6.so: $(objpfx)neededobj5.so -$(objpfx)unload2mod.so: $(objpfx)unload2dep.so -$(objpfx)ltglobmod2.so: $(libdl) -$(objpfx)firstobj.so: $(shared-thread-library) -$(objpfx)globalmod1.so: $(libdl) -$(objpfx)reldep4mod1.so: $(objpfx)reldep4mod3.so -$(objpfx)reldep4mod2.so: $(objpfx)reldep4mod4.so -$(objpfx)dblloadmod1.so: $(objpfx)dblloadmod3.so -$(objpfx)dblloadmod2.so: $(objpfx)dblloadmod3.so -$(objpfx)reldepmod5.so: $(objpfx)reldepmod2.so -$(objpfx)reldepmod6.so: $(objpfx)reldepmod2.so -$(objpfx)reldep6mod1.so: $(objpfx)reldep6mod0.so -$(objpfx)reldep6mod2.so: $(objpfx)reldep6mod1.so -$(objpfx)reldep6mod3.so: $(objpfx)reldep6mod2.so -$(objpfx)reldep6mod4.so: $(objpfx)reldep6mod1.so -$(objpfx)tst-tlsmod3.so: $(objpfx)tst-tlsmod2.so -$(objpfx)tst-tlsmod8.so: $(objpfx)tst-tlsmod7.so -$(objpfx)tst-tlsmod10.so: $(objpfx)tst-tlsmod9.so -$(objpfx)tst-tlsmod12.so: $(objpfx)tst-tlsmod11.so -$(objpfx)tst-tlsmod13a.so: $(objpfx)tst-tlsmod13.so -# For tst-tls9-static, make sure the modules it dlopens have libc.so in DT_NEEDED -$(objpfx)tst-tlsmod5.so: $(common-objpfx)libc.so -$(objpfx)tst-tlsmod6.so: $(common-objpfx)libc.so -$(objpfx)tst-tls19mod1.so: $(objpfx)tst-tls19mod2.so $(objpfx)tst-tls19mod3.so -$(objpfx)tst-tls19mod3.so: $(objpfx)ld.so -$(objpfx)reldep8mod3.so: $(objpfx)reldep8mod1.so $(objpfx)reldep8mod2.so -$(objpfx)nodel2mod3.so: $(objpfx)nodel2mod1.so $(objpfx)nodel2mod2.so -$(objpfx)reldep9mod2.so: $(objpfx)reldep9mod1.so -$(objpfx)reldep9mod3.so: $(objpfx)reldep9mod1.so $(objpfx)reldep9mod2.so -$(objpfx)unload3mod1.so: $(objpfx)unload3mod3.so -$(objpfx)unload3mod2.so: $(objpfx)unload3mod3.so -$(objpfx)unload3mod3.so: $(objpfx)unload3mod4.so -$(objpfx)unload4mod1.so: $(objpfx)unload4mod2.so $(objpfx)unload4mod3.so -$(objpfx)unload4mod2.so: $(objpfx)unload4mod4.so $(objpfx)unload4mod3.so -$(objpfx)unload6mod1.so: $(libdl) -$(objpfx)unload6mod2.so: $(libdl) -$(objpfx)unload6mod3.so: $(libdl) -$(objpfx)unload7mod1.so: $(libdl) -$(objpfx)unload7mod2.so: $(objpfx)unload7mod1.so -$(objpfx)unload8mod1.so: $(objpfx)unload8mod2.so -$(objpfx)unload8mod2.so: $(objpfx)unload8mod3.so -$(objpfx)unload8mod3.so: $(libdl) -$(objpfx)tst-initordera2.so: $(objpfx)tst-initordera1.so -$(objpfx)tst-initorderb2.so: $(objpfx)tst-initorderb1.so $(objpfx)tst-initordera2.so -$(objpfx)tst-initordera3.so: $(objpfx)tst-initorderb2.so $(objpfx)tst-initorderb1.so -$(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-noload: $(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) -LDFLAGS-reldepmod5.so = $(no-as-needed) -LDFLAGS-reldep6mod1.so = $(no-as-needed) -LDFLAGS-reldep6mod4.so = $(no-as-needed) -LDFLAGS-reldep8mod3.so = $(no-as-needed) -LDFLAGS-unload4mod1.so = $(no-as-needed) -LDFLAGS-unload4mod2.so = $(no-as-needed) -LDFLAGS-tst-initorder = $(no-as-needed) -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 $(no-as-needed) -LDFLAGS-tst-tlsmod6.so = -nostdlib $(no-as-needed) - -testobj1.so-no-z-defs = yes -testobj3.so-no-z-defs = yes -testobj4.so-no-z-defs = yes -testobj5.so-no-z-defs = yes -testobj6.so-no-z-defs = yes -failobj.so-no-z-defs = yes -constload2.so-no-z-defs = yes -constload3.so-no-z-defs = yes -nodelmod1.so-no-z-defs = yes -nodelmod2.so-no-z-defs = yes -nodelmod4.so-no-z-defs = yes -nodel2mod2.so-no-z-defs = yes -reldepmod2.so-no-z-defs = yes -reldepmod3.so-no-z-defs = yes -reldepmod4.so-no-z-defs = yes -reldep4mod4.so-no-z-defs = yes -reldep4mod2.so-no-z-defs = yes -ltglobmod2.so-no-z-defs = yes -dblloadmod3.so-no-z-defs = yes -tst-tlsmod1.so-no-z-defs = yes -tst-tlsmod2.so-no-z-defs = yes -tst-tlsmod3.so-no-z-defs = yes -tst-tlsmod4.so-no-z-defs = yes -tst-tlsmod7.so-no-z-defs = yes -tst-tlsmod8.so-no-z-defs = yes -tst-tlsmod9.so-no-z-defs = yes -tst-tlsmod10.so-no-z-defs = yes -tst-tlsmod12.so-no-z-defs = yes -tst-tlsmod14a.so-no-z-defs = yes -tst-tlsmod14b.so-no-z-defs = yes -tst-tlsmod15a.so-no-z-defs = yes -tst-tlsmod16b.so-no-z-defs = yes -circlemod2.so-no-z-defs = yes -circlemod3.so-no-z-defs = yes -circlemod3a.so-no-z-defs = yes -reldep8mod2.so-no-z-defs = yes -reldep9mod1.so-no-z-defs = yes -unload3mod4.so-no-z-defs = yes -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 -tst-nodelete2mod.so-no-z-defs = yes - -ifeq ($(build-shared),yes) -# Build all the modules even when not actually running test programs. -tests: $(test-modules) -endif - -$(objpfx)loadtest: $(libdl) -LDFLAGS-loadtest = -rdynamic - -$(objpfx)loadtest.out: $(test-modules) - -$(objpfx)neededtest: $(libdl) -$(objpfx)neededtest.out: $(objpfx)neededobj1.so $(objpfx)neededobj2.so \ - $(objpfx)neededobj3.so - -$(objpfx)neededtest2: $(libdl) -$(objpfx)neededtest2.out: $(objpfx)neededobj1.so $(objpfx)neededobj2.so \ - $(objpfx)neededobj3.so - -$(objpfx)neededtest3: $(libdl) -$(objpfx)neededtest3.out: $(objpfx)neededobj1.so $(objpfx)neededobj2.so \ - $(objpfx)neededobj3.so $(objpfx)neededobj4.so - -$(objpfx)neededtest4: $(libdl) $(objpfx)neededobj1.so -$(objpfx)neededtest4.out: $(objpfx)neededobj5.so $(objpfx)neededobj6.so - -$(objpfx)restest1: $(objpfx)testobj1.so $(objpfx)testobj1_1.so $(libdl) -LDFLAGS-restest1 = -rdynamic - -$(objpfx)restest2: $(libdl) -LDFLAGS-restest2 = -rdynamic - -$(objpfx)restest1.out: $(test-modules) - -preloadtest-preloads = testobj1 testobj2 testobj3 testobj4 testobj5 -$(objpfx)preloadtest: $(objpfx)testobj6.so -LDFLAGS-preloadtest = -rdynamic -$(objpfx)preloadtest.out: $(preloadtest-preloads:%=$(objpfx)%.so) -preloadtest-ENV = \ - LD_PRELOAD=$(subst $(empty) ,:,$(strip $(preloadtest-preloads:=.so))) - -$(objpfx)loadfail: $(libdl) -LDFLAGS-loadfail = -rdynamic - -$(objpfx)loadfail.out: $(objpfx)failobj.so - -$(objpfx)multiload: $(libdl) -LDFLAGS-multiload = -rdynamic -CFLAGS-multiload.c = -DOBJDIR=\"$(elf-objpfx)\" - -$(objpfx)multiload.out: $(objpfx)testobj1.so - -$(objpfx)origtest: $(libdl) -LDFLAGS-origtest = -rdynamic -$(objpfx)origtest.out: $(objpfx)testobj1.so - -ifeq ($(have-thread-library),yes) -$(objpfx)resolvfail: $(libdl) $(shared-thread-library) -else -$(objpfx)resolvfail: $(libdl) -endif - -$(objpfx)constload1: $(libdl) -$(objpfx)constload1.out: $(objpfx)constload2.so $(objpfx)constload3.so - -$(objpfx)circleload1: $(libdl) -$(objpfx)circleload1.out: $(objpfx)circlemod1.so \ - $(objpfx)circlemod1a.so - -$(objpfx)circlemod1.so: $(objpfx)circlemod2.so -$(objpfx)circlemod2.so: $(objpfx)circlemod3.so -$(objpfx)circlemod1a.so: $(objpfx)circlemod2a.so -$(objpfx)circlemod2a.so: $(objpfx)circlemod3a.so - -$(objpfx)order: $(addprefix $(objpfx),dep4.so dep3.so dep2.so dep1.so) - -$(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 $(libdl) -LDFLAGS-noload = -rdynamic $(no-as-needed) -$(objpfx)noload.out: $(objpfx)testobj5.so - -$(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 -LDFLAGS-nodelmod1.so = -Wl,--enable-new-dtags,-z,nodelete -LDFLAGS-nodelmod4.so = -Wl,--enable-new-dtags,-z,nodelete -$(objpfx)nodelete: $(libdl) -$(objpfx)nodelete.out: $(objpfx)nodelmod1.so $(objpfx)nodelmod2.so \ - $(objpfx)nodelmod3.so - -LDFLAGS-nodlopenmod.so = -Wl,--enable-new-dtags,-z,nodlopen -$(objpfx)nodlopen: $(libdl) -$(objpfx)nodlopen.out: $(objpfx)nodlopenmod.so - -$(objpfx)nodlopenmod2.so: $(objpfx)nodlopenmod.so -$(objpfx)nodlopen2: $(libdl) -$(objpfx)nodlopen2.out: $(objpfx)nodlopenmod2.so - -$(objpfx)filtmod1.so: $(objpfx)filtmod1.os $(objpfx)filtmod2.so - $(LINK.o) -shared -o $@ -B$(csu-objpfx) $(LDFLAGS.so) \ - -L$(subst :, -L,$(rpath-link)) \ - -Wl,-rpath-link=$(rpath-link) \ - $< -Wl,-F,$(objpfx)filtmod2.so -$(objpfx)filter: $(objpfx)filtmod1.so - -# This does not link against libc. -CFLAGS-filtmod1.c = $(no-stack-protector) - -$(objpfx)unload: $(libdl) -$(objpfx)unload.out: $(objpfx)unloadmod.so - -$(objpfx)reldep: $(libdl) -$(objpfx)reldep.out: $(objpfx)reldepmod1.so $(objpfx)reldepmod2.so - -$(objpfx)reldep2: $(libdl) -$(objpfx)reldep2.out: $(objpfx)reldepmod1.so $(objpfx)reldepmod3.so - -$(objpfx)reldep3: $(libdl) -$(objpfx)reldep3.out: $(objpfx)reldepmod1.so $(objpfx)reldepmod4.so - -$(objpfx)reldep4: $(libdl) -$(objpfx)reldep4.out: $(objpfx)reldep4mod1.so $(objpfx)reldep4mod2.so - -$(objpfx)next: $(objpfx)nextmod1.so $(objpfx)nextmod2.so $(libdl) -LDFLAGS-next = $(no-as-needed) - -$(objpfx)unload2: $(libdl) -$(objpfx)unload2.out: $(objpfx)unload2mod.so $(objpfx)unload2dep.so - -$(objpfx)lateglobal: $(libdl) -$(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)' \ - '$(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)' > $@; \ - $(evaluate-test) - -$(objpfx)initfirst: $(libdl) -$(objpfx)initfirst.out: $(objpfx)firstobj.so - -$(objpfx)global: $(objpfx)globalmod1.so -$(objpfx)global.out: $(objpfx)reldepmod1.so - -$(objpfx)dblload: $(libdl) -$(objpfx)dblload.out: $(objpfx)dblloadmod1.so $(objpfx)dblloadmod2.so - -$(objpfx)dblunload: $(libdl) -$(objpfx)dblunload.out: $(objpfx)dblloadmod1.so $(objpfx)dblloadmod2.so - -$(objpfx)reldep5: $(libdl) -$(objpfx)reldep5.out: $(objpfx)reldepmod5.so $(objpfx)reldepmod6.so - -$(objpfx)reldep6: $(libdl) -$(objpfx)reldep6.out: $(objpfx)reldep6mod3.so $(objpfx)reldep6mod4.so - -$(objpfx)reldep7: $(libdl) -$(objpfx)reldep7.out: $(objpfx)reldep7mod1.so $(objpfx)reldep7mod2.so - -$(objpfx)reldep8: $(libdl) -$(objpfx)reldep8.out: $(objpfx)reldep8mod3.so - -LDFLAGS-nodel2mod2.so = -Wl,--enable-new-dtags,-z,nodelete -$(objpfx)nodelete2: $(libdl) -$(objpfx)nodelete2.out: $(objpfx)nodel2mod3.so - -$(objpfx)reldep9: $(libdl) -$(objpfx)reldep9.out: $(objpfx)reldep9mod3.so - -$(objpfx)tst-tls3: $(objpfx)tst-tlsmod1.so - -$(objpfx)tst-tls4: $(libdl) -$(objpfx)tst-tls4.out: $(objpfx)tst-tlsmod2.so - -$(objpfx)tst-tls5: $(libdl) -$(objpfx)tst-tls5.out: $(objpfx)tst-tlsmod2.so - -$(objpfx)tst-tls6: $(libdl) -$(objpfx)tst-tls6.out: $(objpfx)tst-tlsmod2.so - -$(objpfx)tst-tls7: $(libdl) -$(objpfx)tst-tls7.out: $(objpfx)tst-tlsmod3.so - -$(objpfx)tst-tls8: $(libdl) -$(objpfx)tst-tls8.out: $(objpfx)tst-tlsmod3.so $(objpfx)tst-tlsmod4.so - -$(objpfx)tst-tls9: $(libdl) -$(objpfx)tst-tls9.out: $(objpfx)tst-tlsmod5.so $(objpfx)tst-tlsmod6.so - -$(objpfx)tst-tls10: $(objpfx)tst-tlsmod8.so $(objpfx)tst-tlsmod7.so - -$(objpfx)tst-tls11: $(objpfx)tst-tlsmod10.so $(objpfx)tst-tlsmod9.so - -$(objpfx)tst-tls12: $(objpfx)tst-tlsmod12.so $(objpfx)tst-tlsmod11.so - -$(objpfx)tst-tls13: $(libdl) -$(objpfx)tst-tls13.out: $(objpfx)tst-tlsmod13a.so - -$(objpfx)tst-tls14: $(objpfx)tst-tlsmod14a.so $(libdl) -$(objpfx)tst-tls14.out: $(objpfx)tst-tlsmod14b.so - -$(objpfx)tst-tls15: $(libdl) -$(objpfx)tst-tls15.out: $(objpfx)tst-tlsmod15a.so $(objpfx)tst-tlsmod15b.so - -$(objpfx)tst-tls-dlinfo: $(libdl) -$(objpfx)tst-tls-dlinfo.out: $(objpfx)tst-tlsmod2.so - - - -$(objpfx)tst-tls16: $(libdl) -$(objpfx)tst-tls16.out: $(objpfx)tst-tlsmod16a.so $(objpfx)tst-tlsmod16b.so - -$(objpfx)tst-tls17: $(libdl) -$(objpfx)tst-tls17.out: $(objpfx)tst-tlsmod17b.so -$(patsubst %,$(objpfx)%.os,$(tlsmod17a-modules)): $(objpfx)tst-tlsmod17a%.os: tst-tlsmod17a.c - $(compile-command.c) -DN=$* -$(patsubst %,$(objpfx)%.so,$(tlsmod17a-modules)): $(objpfx)tst-tlsmod17a%.so: $(objpfx)ld.so -$(objpfx)tst-tlsmod17b.so: $(patsubst %,$(objpfx)%.so,$(tlsmod17a-modules)) - -$(objpfx)tst-tls18: $(libdl) -$(objpfx)tst-tls18.out: $(patsubst %,$(objpfx)%.so,$(tlsmod18a-modules)) -$(patsubst %,$(objpfx)%.os,$(tlsmod18a-modules)): $(objpfx)tst-tlsmod18a%.os : tst-tlsmod18a.c - $(compile-command.c) -DN=$* -$(patsubst %,$(objpfx)%.so,$(tlsmod18a-modules)): $(objpfx)tst-tlsmod18a%.so: $(objpfx)ld.so - -$(objpfx)tst-tls19: $(libdl) -$(objpfx)tst-tls19.out: $(objpfx)tst-tls19mod1.so - -CFLAGS-tst-align.c = $(stack-align-test-flags) -CFLAGS-tst-align2.c = $(stack-align-test-flags) -CFLAGS-tst-alignmod.c = $(stack-align-test-flags) -CFLAGS-tst-alignmod2.c = $(stack-align-test-flags) -$(objpfx)tst-align: $(libdl) -$(objpfx)tst-align.out: $(objpfx)tst-alignmod.so -$(objpfx)tst-align2: $(objpfx)tst-alignmod2.so - -$(objpfx)unload3: $(libdl) -$(objpfx)unload3.out: $(objpfx)unload3mod1.so $(objpfx)unload3mod2.so \ - $(objpfx)unload3mod3.so $(objpfx)unload3mod4.so - -$(objpfx)unload4: $(libdl) -$(objpfx)unload4.out: $(objpfx)unload4mod1.so $(objpfx)unload4mod3.so - -$(objpfx)unload5: $(libdl) -$(objpfx)unload5.out: $(objpfx)unload3mod1.so $(objpfx)unload3mod2.so \ - $(objpfx)unload3mod3.so $(objpfx)unload3mod4.so - -$(objpfx)unload6: $(libdl) -$(objpfx)unload6.out: $(objpfx)unload6mod1.so $(objpfx)unload6mod2.so \ - $(objpfx)unload6mod3.so - -$(objpfx)unload7: $(libdl) -$(objpfx)unload7.out: $(objpfx)unload7mod1.so $(objpfx)unload7mod2.so -unload7-ENV = MALLOC_PERTURB_=85 - -$(objpfx)unload8: $(libdl) -$(objpfx)unload8.out: $(objpfx)unload8mod1.so $(objpfx)unload8mod1x.so - -ifdef libdl -$(objpfx)tst-tls9-static: $(common-objpfx)dlfcn/libdl.a -$(objpfx)tst-tls9-static.out: $(objpfx)tst-tlsmod5.so $(objpfx)tst-tlsmod6.so -endif - -ifeq ($(have-z-execstack),yes) -$(objpfx)tst-execstack: $(libdl) -$(objpfx)tst-execstack.out: $(objpfx)tst-execstack-mod.so -CPPFLAGS-tst-execstack.c = -DUSE_PTHREADS=0 -LDFLAGS-tst-execstack = -Wl,-z,noexecstack -LDFLAGS-tst-execstack-mod = -Wl,-z,execstack - -$(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-cmp.out: tst-array1.exp $(objpfx)tst-array1.out - cmp $^ > $@; \ - $(evaluate-test) - -$(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-cmp.out: tst-array2.exp $(objpfx)tst-array2.out - cmp $^ > $@; \ - $(evaluate-test) - -$(objpfx)tst-array3-cmp.out: tst-array1.exp $(objpfx)tst-array3.out - cmp $^ > $@; \ - $(evaluate-test) - -$(objpfx)tst-array4: $(libdl) -$(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-cmp.out: tst-array5.exp $(objpfx)tst-array5.out - cmp $^ > $@; \ - $(evaluate-test) - -$(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-piemod1.so: $(libsupport) -$(objpfx)tst-pie1: $(objpfx)tst-piemod1.so - -ifeq (yes,$(build-shared)) -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 \ - iconvdata/*.so)))) - -$(all-built-dso:=.dyn): %.dyn: % - @rm -f $@T - LC_ALL=C $(READELF) -W -d $< > $@T - test -s $@T - mv -f $@T $@ -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 $^ > $@; \ - $(evaluate-test) -generated += check-textrel.out - -$(objpfx)execstack-default: $(first-word $(wildcard $(sysdirs:%=%/stackinfo.h))) - $(make-target-directory) - { echo '#include <elf.h>'; \ - echo '#include <stackinfo.h>'; \ - echo '#if (DEFAULT_STACK_PERMS & PF_X) == 0'; \ - echo '@@@execstack-no@@@'; \ - echo '#else'; \ - echo '@@@execstack-yes@@@'; \ - echo '#endif'; } | \ - $(CC) $(CFLAGS) $(CPPFLAGS) -E -x c-header - | \ - sed -n -e 's/^@@@\(.*\)@@@/\1/p' > $@T - mv -f $@T $@ -generated += execstack-default - -$(all-built-dso:=.phdr): %.phdr: % - @rm -f $@T - LC_ALL=C $(READELF) -W -l $< > $@T - test -s $@T - mv -f $@T $@ -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 $^ > $@; \ - $(evaluate-test) -generated += check-execstack.out - -$(objpfx)tst-dlmodcount: $(libdl) -$(objpfx)tst-dlmodcount.out: $(test-modules) - -$(all-built-dso:=.jmprel): %.jmprel: % Makefile - @rm -f $@T - LC_ALL=C $(READELF) -W -S -d -r $< > $@T - test -s $@T - mv -f $@T $@ -common-generated += $(all-built-dso:$(common-objpfx)%=%.jmprel) - -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 - -vpath localplt.data $(+sysdep_dirs) - -$(objpfx)check-localplt.out: $(..)scripts/check-localplt.awk \ - $(..)scripts/localplt.awk \ - $(localplt-built-dso:=.jmprel) \ - 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) -$(objpfx)tst-dlopenrpath: $(objpfx)tst-dlopenrpathmod.so $(libdl) -CFLAGS-tst-dlopenrpath.c += -DPFX=\"$(objpfx)\" -LDFLAGS-tst-dlopenrpathmod.so += -Wl,-rpath,\$$ORIGIN/test-subdir -$(objpfx)tst-dlopenrpath.out: $(objpfx)firstobj.so - -$(objpfx)tst-deep1mod2.so: $(objpfx)tst-deep1mod3.so -$(objpfx)tst-deep1: $(libdl) $(objpfx)tst-deep1mod1.so -$(objpfx)tst-deep1.out: $(objpfx)tst-deep1mod2.so -LDFLAGS-tst-deep1 += -rdynamic -tst-deep1mod3.so-no-z-defs = yes - -$(objpfx)tst-dlmopen1mod.so: $(libdl) -$(objpfx)tst-dlmopen1: $(libdl) -$(objpfx)tst-dlmopen1.out: $(objpfx)tst-dlmopen1mod.so - -$(objpfx)tst-dlmopen2: $(libdl) -$(objpfx)tst-dlmopen2.out: $(objpfx)tst-dlmopen1mod.so - -$(objpfx)tst-dlmopen3: $(libdl) -$(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: $(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-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 - -$(objpfx)tst-global1: $(libdl) -$(objpfx)tst-global1.out: $(objpfx)testobj6.so $(objpfx)testobj2.so - -$(objpfx)order2: $(libdl) -$(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 -order2mod2.so-no-z-defs = yes -LDFLAGS-order2mod1.so = $(no-as-needed) -LDFLAGS-order2mod2.so = $(no-as-needed) - -tst-stackguard1-ARGS = --command "$(host-test-program-cmd) --child" -tst-stackguard1-static-ARGS = --command "$(objpfx)tst-stackguard1-static --child" - -tst-ptrguard1-ARGS = --command "$(host-test-program-cmd) --child" -# When built statically, the pointer guard interface uses -# __pointer_chk_guard_local. -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.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.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 - -$(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) -CFLAGS-ifuncmain1staticpic.c += $(pic-ccflag) -CFLAGS-ifuncdep1pic.c += $(pic-ccflag) -CFLAGS-ifuncmain1vispic.c += $(pic-ccflag) -CFLAGS-ifuncmain2pic.c += $(pic-ccflag) -CFLAGS-ifuncmain2picstatic.c += $(pic-ccflag) -CFLAGS-ifuncdep2pic.c += $(pic-ccflag) -CFLAGS-ifuncmain4picstatic.c += $(pic-ccflag) -CFLAGS-ifuncmain5pic.c += $(pic-ccflag) -CFLAGS-ifuncmain5picstatic.c += $(pic-ccflag) -CFLAGS-ifuncmain5staticpic.c += $(pic-ccflag) -CFLAGS-ifuncdep5pic.c += $(pic-ccflag) -CFLAGS-ifuncmain7pic.c += $(pic-ccflag) -CFLAGS-ifuncmain7picstatic.c += $(pic-ccflag) - -LDFLAGS-ifuncmain3 = -Wl,-export-dynamic - -CFLAGS-ifuncmain1pie.c += $(pie-ccflag) -CFLAGS-ifuncmain1vispie.c += $(pie-ccflag) -CFLAGS-ifuncmain1staticpie.c += $(pie-ccflag) -CFLAGS-ifuncmain5pie.c += $(pie-ccflag) -CFLAGS-ifuncmain6pie.c += $(pie-ccflag) -CFLAGS-ifuncmain7pie.c += $(pie-ccflag) - -$(objpfx)ifuncmain1pie: $(objpfx)ifuncmod1.so -$(objpfx)ifuncmain1staticpie: $(objpfx)ifuncdep1pic.o -$(objpfx)ifuncmain1vispie: $(objpfx)ifuncmod1.so -$(objpfx)ifuncmain5pie: $(objpfx)ifuncmod5.so -$(objpfx)ifuncmain6pie: $(objpfx)ifuncmod6.so - -$(objpfx)ifuncmain1: $(addprefix $(objpfx),ifuncmod1.so) -$(objpfx)ifuncmain1pic: $(addprefix $(objpfx),ifuncmod1.so) -$(objpfx)ifuncmain1staticpic: $(addprefix $(objpfx),ifuncdep1pic.o) -$(objpfx)ifuncmain1static: $(addprefix $(objpfx),ifuncdep1.o) -$(objpfx)ifuncmain1picstatic: $(addprefix $(objpfx),ifuncdep1pic.o) -$(objpfx)ifuncmain1vis: $(addprefix $(objpfx),ifuncmod1.so) -$(objpfx)ifuncmain1vispic: $(addprefix $(objpfx),ifuncmod1.so) -$(objpfx)ifuncmain2: $(addprefix $(objpfx),ifuncdep2.o) -$(objpfx)ifuncmain2pic: $(addprefix $(objpfx),ifuncdep2pic.o) -$(objpfx)ifuncmain2static: $(addprefix $(objpfx),ifuncdep2.o) -$(objpfx)ifuncmain2picstatic: $(addprefix $(objpfx),ifuncdep2pic.o) - -$(objpfx)ifuncmain3: $(libdl) -$(objpfx)ifuncmain3.out: $(objpfx)ifuncmod3.so - -$(objpfx)ifuncmain5: $(addprefix $(objpfx),ifuncmod5.so) -$(objpfx)ifuncmain5pic: $(addprefix $(objpfx),ifuncmod5.so) -$(objpfx)ifuncmain5static: $(addprefix $(objpfx),ifuncdep5.o) -$(objpfx)ifuncmain5staticpic: $(addprefix $(objpfx),ifuncdep5pic.o) -$(objpfx)ifuncmain5picstatic: $(addprefix $(objpfx),ifuncdep5pic.o) - -$(objpfx)tst-unique1: $(libdl) -$(objpfx)tst-unique1.out: $(objpfx)tst-unique1mod1.so \ - $(objpfx)tst-unique1mod2.so - -$(objpfx)tst-unique2: $(libdl) $(objpfx)tst-unique2mod1.so -$(objpfx)tst-unique2.out: $(objpfx)tst-unique2mod2.so - -$(objpfx)tst-unique3: $(libdl) $(objpfx)tst-unique3lib.so -$(objpfx)tst-unique3.out: $(objpfx)tst-unique3lib2.so - -$(objpfx)tst-unique4: $(objpfx)tst-unique4lib.so - -$(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-nodelete2: $(libdl) -$(objpfx)tst-nodelete2.out: $(objpfx)tst-nodelete2mod.so - -LDFLAGS-tst-nodelete2 = -rdynamic - -$(objpfx)tst-initorder-cmp.out: tst-initorder.exp $(objpfx)tst-initorder.out - cmp $^ > $@; \ - $(evaluate-test) - -$(objpfx)tst-initorder2: $(objpfx)tst-initorder2a.so $(objpfx)tst-initorder2d.so $(objpfx)tst-initorder2c.so -$(objpfx)tst-initorder2a.so: $(objpfx)tst-initorder2b.so -$(objpfx)tst-initorder2b.so: $(objpfx)tst-initorder2c.so -$(objpfx)tst-initorder2c.so: $(objpfx)tst-initorder2d.so -LDFLAGS-tst-initorder2 = $(no-as-needed) -LDFLAGS-tst-initorder2a.so = $(no-as-needed) -LDFLAGS-tst-initorder2b.so = $(no-as-needed) -LDFLAGS-tst-initorder2c.so = $(no-as-needed) -define o-iterator-doit -$(objpfx)tst-initorder2$o.os: tst-initorder2.c; \ -$$(compile-command.c) -DNAME=\"$o\" -endef -object-suffixes-left := a b c d -include $(o-iterator) - -$(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 -$(objpfx)tst-relsort1mod2.so: $(libm) -$(objpfx)tst-relsort1.out: $(objpfx)tst-relsort1mod1.so \ - $(objpfx)tst-relsort1mod2.so - -$(objpfx)tst-unused-dep.out: $(objpfx)testobj1.so - $(test-wrapper-env) \ - LD_TRACE_LOADED_OBJECTS=1 \ - LD_DEBUG=unused \ - LD_PRELOAD= \ - $(rtld-prefix) \ - $< > $@; \ - $(evaluate-test) - -$(objpfx)tst-unused-dep-cmp.out: $(objpfx)tst-unused-dep.out - cmp $< /dev/null > $@; \ - $(evaluate-test) - -$(objpfx)tst-audit11.out: $(objpfx)tst-auditmod11.so $(objpfx)tst-audit11mod1.so -$(objpfx)tst-audit11: $(libdl) -tst-audit11-ENV = LD_AUDIT=$(objpfx)tst-auditmod11.so -$(objpfx)tst-audit11mod1.so: $(objpfx)tst-audit11mod2.so -LDFLAGS-tst-audit11mod2.so = -Wl,--version-script=tst-audit11mod2.map,-soname,tst-audit11mod2.so - -$(objpfx)tst-audit12.out: $(objpfx)tst-auditmod12.so $(objpfx)tst-audit12mod1.so $(objpfx)tst-audit12mod3.so -$(objpfx)tst-audit12: $(libdl) -tst-audit12-ENV = LD_AUDIT=$(objpfx)tst-auditmod12.so -$(objpfx)tst-audit12mod1.so: $(objpfx)tst-audit12mod2.so -LDFLAGS-tst-audit12mod2.so = -Wl,--version-script=tst-audit12mod2.map - -# Override -z defs, so that we can reference an undefined symbol. -# Force lazy binding for the same reason. -LDFLAGS-tst-latepthreadmod.so = \ - -Wl,-z,lazy -Wl,--unresolved-symbols=ignore-all -# Do not optimize sibling calls as the test relies on a JMP_SLOT relocation for -# function this_function_is_not_defined. -CFLAGS-tst-latepthreadmod.c = -fno-optimize-sibling-calls -$(objpfx)tst-latepthreadmod.so: $(shared-thread-library) -$(objpfx)tst-latepthread: $(libdl) -$(objpfx)tst-latepthread.out: $(objpfx)tst-latepthreadmod.so - -# The test modules are parameterized by preprocessor macros. -$(patsubst %,$(objpfx)%.os,$(tst-tls-many-dynamic-modules)): \ - $(objpfx)tst-tls-manydynamic%mod.os : tst-tls-manydynamicmod.c - $(compile-command.c) \ - -DNAME=tls_global_$* -DSETTER=set_value_$* -DGETTER=get_value_$* -$(objpfx)tst-tls-manydynamic: $(libdl) $(shared-thread-library) -$(objpfx)tst-tls-manydynamic.out: \ - $(patsubst %,$(objpfx)%.so,$(tst-tls-many-dynamic-modules)) - -tst-prelink-ENV = LD_TRACE_PRELINKING=1 - -$(objpfx)tst-prelink-conflict.out: $(objpfx)tst-prelink.out - grep stdout $< | grep conflict | $(AWK) '{ print $$10, $$11 }' > $@ - -$(objpfx)tst-prelink-cmp.out: tst-prelink.exp \ - $(objpfx)tst-prelink-conflict.out - cmp $^ > $@; \ - $(evaluate-test) - -$(objpfx)tst-ldconfig-X.out : tst-ldconfig-X.sh $(objpfx)ldconfig - $(SHELL) $< '$(common-objpfx)' '$(test-wrapper-env)' \ - '$(run-program-env)' > $@; \ - $(evaluate-test) - -$(objpfx)tst-dlsym-error: $(libdl) - -# Test static linking of all the libraries we can possibly link -# together. Note that in some configurations this may be less than the -# complete list of libraries we build but we try to maxmimize this list. -$(objpfx)tst-linkall-static: \ - $(common-objpfx)math/libm.a \ - $(common-objpfx)resolv/libresolv.a \ - $(common-objpfx)dlfcn/libdl.a \ - $(common-objpfx)login/libutil.a \ - $(common-objpfx)rt/librt.a \ - $(common-objpfx)resolv/libanl.a \ - $(static-thread-library) - -# If we are using NSS crypto and we have the ability to link statically -# then we include libcrypt.a, otherwise we leave out libcrypt.a and -# link as much as we can into the tst-linkall-static test. This assumes -# that linking with libcrypt.a does everything required to include the -# static NSS crypto library. -ifeq (yesyes,$(nss-crypt)$(static-nss-crypt)) -$(objpfx)tst-linkall-static: \ - $(common-objpfx)crypt/libcrypt.a -endif -# If we are not using NSS crypto then we always have the ability to link -# with libcrypt.a. -ifeq (no,$(nss-crypt)) -$(objpfx)tst-linkall-static: \ - $(common-objpfx)crypt/libcrypt.a -endif - -# The application depends on the DSO, and the DSO loads the plugin. -# The plugin also depends on the DSO. This creates the circular -# dependency via dlopen that we're testing to make sure works. -$(objpfx)tst-nodelete-dlclose-dso.so: $(libdl) -$(objpfx)tst-nodelete-dlclose-plugin.so: $(objpfx)tst-nodelete-dlclose-dso.so -$(objpfx)tst-nodelete-dlclose: $(objpfx)tst-nodelete-dlclose-dso.so -$(objpfx)tst-nodelete-dlclose.out: $(objpfx)tst-nodelete-dlclose-dso.so \ - $(objpfx)tst-nodelete-dlclose-plugin.so - -tst-env-setuid-ENV = MALLOC_CHECK_=2 MALLOC_MMAP_THRESHOLD_=4096 \ - LD_HWCAP_MASK=0x1 -tst-env-setuid-tunables-ENV = \ - GLIBC_TUNABLES=glibc.malloc.check=2:glibc.malloc.mmap_threshold=4096 diff --git a/elf/Versions b/elf/Versions deleted file mode 100644 index c59facdbd7..0000000000 --- a/elf/Versions +++ /dev/null @@ -1,77 +0,0 @@ -libc { - GLIBC_2.0 { -%ifdef EXPORT_UNWIND_FIND_FDE - __deregister_frame_info; __register_frame_info; -%endif - } - GLIBC_2.1 { - # functions used in other libraries - _dl_mcount_wrapper; _dl_mcount_wrapper_check; - } - GLIBC_2.2.4 { - 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; - } -%endif - GLIBC_PRIVATE { - # functions used in other libraries - _dl_addr; - _dl_open_hook; - _dl_sym; _dl_vsym; - __libc_dlclose; __libc_dlopen_mode; __libc_dlsym; - - # Internal error handling support. Interposes the functions in ld.so. - _dl_signal_error; _dl_catch_error; - } -} - -ld { - GLIBC_2.0 { - # Functions which are interposed from libc.so. - calloc; free; malloc; realloc; - - _r_debug; - } - GLIBC_2.1 { - # functions used in other libraries - _dl_mcount; - # historically used by Garbage Collectors - __libc_stack_end; - } - GLIBC_2.3 { - # runtime interface to TLS - __tls_get_addr; - } - GLIBC_2.4 { - # stack canary - __stack_chk_guard; - } - GLIBC_PRIVATE { - # Those are in the dynamic linker, but used by libc.so. - __libc_enable_secure; - _dl_allocate_tls; _dl_allocate_tls_init; - _dl_argv; _dl_find_dso_for_object; _dl_get_tls_static_info; - _dl_deallocate_tls; _dl_make_stack_executable; _dl_out_of_memory; - _dl_rtld_di_serinfo; _dl_starting_up; - _rtld_global; _rtld_global_ro; - - # Only here for gdb while a better method is developed. - _dl_debug_state; - - # Pointer protection. - __pointer_chk_guard; - - # Internal error handling support. Interposed by libc.so. - _dl_signal_error; _dl_catch_error; - - # Set value of a tunable. - __tunable_get_val; - } -} diff --git a/elf/cache.c b/elf/cache.c deleted file mode 100644 index a76f89281d..0000000000 --- a/elf/cache.c +++ /dev/null @@ -1,829 +0,0 @@ -/* Copyright (C) 1999-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Andreas Jaeger <aj@suse.de>, 1999. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, see <http://www.gnu.org/licenses/>. */ - -#include <errno.h> -#include <error.h> -#include <dirent.h> -#include <inttypes.h> -#include <libgen.h> -#include <libintl.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <stdint.h> -#include <sys/fcntl.h> -#include <sys/mman.h> -#include <sys/stat.h> -#include <sys/types.h> - -#include <ldconfig.h> -#include <dl-cache.h> - -struct cache_entry -{ - char *lib; /* Library name. */ - char *path; /* Path to find library. */ - int flags; /* Flags to indicate kind of library. */ - unsigned int osversion; /* Required OS version. */ - uint64_t hwcap; /* Important hardware capabilities. */ - int bits_hwcap; /* Number of bits set in hwcap. */ - struct cache_entry *next; /* Next entry in list. */ -}; - -/* List of all cache entries. */ -static struct cache_entry *entries; - -static const char *flag_descr[] = -{ "libc4", "ELF", "libc5", "libc6"}; - -/* Print a single entry. */ -static void -print_entry (const char *lib, int flag, unsigned int osversion, - uint64_t hwcap, const char *key) -{ - printf ("\t%s (", lib); - switch (flag & FLAG_TYPE_MASK) - { - case FLAG_LIBC4: - case FLAG_ELF: - case FLAG_ELF_LIBC5: - case FLAG_ELF_LIBC6: - fputs (flag_descr[flag & FLAG_TYPE_MASK], stdout); - break; - default: - fputs (_("unknown"), stdout); - break; - } - switch (flag & FLAG_REQUIRED_MASK) - { - case FLAG_SPARC_LIB64: - fputs (",64bit", stdout); - break; - case FLAG_IA64_LIB64: - fputs (",IA-64", stdout); - break; - case FLAG_X8664_LIB64: - fputs (",x86-64", stdout); - break; - case FLAG_S390_LIB64: - fputs (",64bit", stdout); - break; - case FLAG_POWERPC_LIB64: - fputs (",64bit", stdout); - break; - case FLAG_MIPS64_LIBN32: - fputs (",N32", stdout); - break; - case FLAG_MIPS64_LIBN64: - fputs (",64bit", stdout); - break; - case FLAG_X8664_LIBX32: - fputs (",x32", stdout); - break; - case FLAG_ARM_LIBHF: - fputs (",hard-float", stdout); - break; - case FLAG_AARCH64_LIB64: - fputs (",AArch64", stdout); - break; - /* Uses the ARM soft-float ABI. */ - case FLAG_ARM_LIBSF: - fputs (",soft-float", stdout); - break; - case FLAG_MIPS_LIB32_NAN2008: - fputs (",nan2008", stdout); - break; - case FLAG_MIPS64_LIBN32_NAN2008: - fputs (",N32,nan2008", stdout); - break; - case FLAG_MIPS64_LIBN64_NAN2008: - fputs (",64bit,nan2008", stdout); - break; - case 0: - break; - default: - printf (",%d", flag & FLAG_REQUIRED_MASK); - break; - } - if (hwcap != 0) - printf (", hwcap: %#.16" PRIx64, hwcap); - if (osversion != 0) - { - static const char *const abi_tag_os[] = - { - [0] = "Linux", - [1] = "Hurd", - [2] = "Solaris", - [3] = "FreeBSD", - [4] = "kNetBSD", - [5] = "Syllable", - [6] = N_("Unknown OS") - }; -#define MAXTAG (sizeof abi_tag_os / sizeof abi_tag_os[0] - 1) - unsigned int os = osversion >> 24; - - printf (_(", OS ABI: %s %d.%d.%d"), - _(abi_tag_os[os > MAXTAG ? MAXTAG : os]), - (osversion >> 16) & 0xff, - (osversion >> 8) & 0xff, - osversion & 0xff); - } - printf (") => %s\n", key); -} - - -/* Print the whole cache file, if a file contains the new cache format - hidden in the old one, print the contents of the new format. */ -void -print_cache (const char *cache_name) -{ - int fd = open (cache_name, O_RDONLY); - if (fd < 0) - error (EXIT_FAILURE, errno, _("Can't open cache file %s\n"), cache_name); - - struct stat64 st; - if (fstat64 (fd, &st) < 0 - /* No need to map the file if it is empty. */ - || st.st_size == 0) - { - close (fd); - return; - } - - struct cache_file *cache - = mmap (NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); - if (cache == MAP_FAILED) - error (EXIT_FAILURE, errno, _("mmap of cache file failed.\n")); - - size_t cache_size = st.st_size; - if (cache_size < sizeof (struct cache_file)) - error (EXIT_FAILURE, 0, _("File is not a cache file.\n")); - - struct cache_file_new *cache_new = NULL; - const char *cache_data; - int format = 0; - - if (memcmp (cache->magic, CACHEMAGIC, sizeof CACHEMAGIC - 1)) - { - /* This can only be the new format without the old one. */ - cache_new = (struct cache_file_new *) cache; - - if (memcmp (cache_new->magic, CACHEMAGIC_NEW, sizeof CACHEMAGIC_NEW - 1) - || memcmp (cache_new->version, CACHE_VERSION, - sizeof CACHE_VERSION - 1)) - error (EXIT_FAILURE, 0, _("File is not a cache file.\n")); - format = 1; - /* This is where the strings start. */ - cache_data = (const char *) cache_new; - } - else - { - size_t offset = ALIGN_CACHE (sizeof (struct cache_file) - + (cache->nlibs - * sizeof (struct file_entry))); - /* This is where the strings start. */ - cache_data = (const char *) &cache->libs[cache->nlibs]; - - /* Check for a new cache embedded in the old format. */ - if (cache_size > - (offset + sizeof (struct cache_file_new))) - { - - cache_new = (struct cache_file_new *) ((void *)cache + offset); - - if (memcmp (cache_new->magic, CACHEMAGIC_NEW, - sizeof CACHEMAGIC_NEW - 1) == 0 - && memcmp (cache_new->version, CACHE_VERSION, - sizeof CACHE_VERSION - 1) == 0) - { - cache_data = (const char *) cache_new; - format = 1; - } - } - } - - if (format == 0) - { - printf (_("%d libs found in cache `%s'\n"), cache->nlibs, cache_name); - - /* Print everything. */ - for (unsigned int i = 0; i < cache->nlibs; i++) - print_entry (cache_data + cache->libs[i].key, - cache->libs[i].flags, 0, 0, - cache_data + cache->libs[i].value); - } - else if (format == 1) - { - printf (_("%d libs found in cache `%s'\n"), - cache_new->nlibs, cache_name); - - /* Print everything. */ - for (unsigned int i = 0; i < cache_new->nlibs; i++) - print_entry (cache_data + cache_new->libs[i].key, - cache_new->libs[i].flags, - cache_new->libs[i].osversion, - cache_new->libs[i].hwcap, - cache_data + cache_new->libs[i].value); - } - /* Cleanup. */ - munmap (cache, cache_size); - close (fd); -} - -/* Initialize cache data structures. */ -void -init_cache (void) -{ - entries = NULL; -} - -static int -compare (const struct cache_entry *e1, const struct cache_entry *e2) -{ - /* We need to swap entries here to get the correct sort order. */ - int res = _dl_cache_libcmp (e2->lib, e1->lib); - if (res == 0) - { - if (e1->flags < e2->flags) - return 1; - else if (e1->flags > e2->flags) - return -1; - /* Sort by most specific hwcap. */ - else if (e2->bits_hwcap > e1->bits_hwcap) - return 1; - else if (e2->bits_hwcap < e1->bits_hwcap) - return -1; - else if (e2->hwcap > e1->hwcap) - return 1; - else if (e2->hwcap < e1->hwcap) - return -1; - if (e2->osversion > e1->osversion) - return 1; - if (e2->osversion < e1->osversion) - return -1; - } - return res; -} - -/* Save the contents of the cache. */ -void -save_cache (const char *cache_name) -{ - /* The cache entries are sorted already, save them in this order. */ - - /* Count the length of all strings. */ - /* The old format doesn't contain hwcap entries and doesn't contain - libraries in subdirectories with hwcaps entries. Count therefore - also all entries with hwcap == 0. */ - size_t total_strlen = 0; - struct cache_entry *entry; - /* Number of cache entries. */ - int cache_entry_count = 0; - /* Number of normal cache entries. */ - int cache_entry_old_count = 0; - - for (entry = entries; entry != NULL; entry = entry->next) - { - /* Account the final NULs. */ - total_strlen += strlen (entry->lib) + strlen (entry->path) + 2; - ++cache_entry_count; - if (entry->hwcap == 0) - ++cache_entry_old_count; - } - - /* Create the on disk cache structure. */ - struct cache_file *file_entries = NULL; - size_t file_entries_size = 0; - - if (opt_format != 2) - { - /* struct cache_file_new is 64-bit aligned on some arches while - only 32-bit aligned on other arches. Duplicate last old - cache entry so that new cache in ld.so.cache can be used by - both. */ - if (opt_format != 0) - cache_entry_old_count = (cache_entry_old_count + 1) & ~1; - - /* And the list of all entries in the old format. */ - file_entries_size = sizeof (struct cache_file) - + cache_entry_old_count * sizeof (struct file_entry); - file_entries = xmalloc (file_entries_size); - - /* Fill in the header. */ - memset (file_entries, '\0', sizeof (struct cache_file)); - memcpy (file_entries->magic, CACHEMAGIC, sizeof CACHEMAGIC - 1); - - file_entries->nlibs = cache_entry_old_count; - } - - struct cache_file_new *file_entries_new = NULL; - size_t file_entries_new_size = 0; - - if (opt_format != 0) - { - /* And the list of all entries in the new format. */ - file_entries_new_size = sizeof (struct cache_file_new) - + cache_entry_count * sizeof (struct file_entry_new); - file_entries_new = xmalloc (file_entries_new_size); - - /* Fill in the header. */ - memset (file_entries_new, '\0', sizeof (struct cache_file_new)); - memcpy (file_entries_new->magic, CACHEMAGIC_NEW, - sizeof CACHEMAGIC_NEW - 1); - memcpy (file_entries_new->version, CACHE_VERSION, - sizeof CACHE_VERSION - 1); - - file_entries_new->nlibs = cache_entry_count; - file_entries_new->len_strings = total_strlen; - } - - /* Pad for alignment of cache_file_new. */ - size_t pad = ALIGN_CACHE (file_entries_size) - file_entries_size; - - /* If we have both formats, we hide the new format in the strings - table, we have to adjust all string indices for this so that - old libc5/glibc 2 dynamic linkers just ignore them. */ - unsigned int str_offset; - if (opt_format != 0) - str_offset = file_entries_new_size; - else - str_offset = 0; - - /* An array for all strings. */ - char *strings = xmalloc (total_strlen); - char *str = strings; - int idx_old; - int idx_new; - - for (idx_old = 0, idx_new = 0, entry = entries; entry != NULL; - entry = entry->next, ++idx_new) - { - /* First the library. */ - if (opt_format != 2 && entry->hwcap == 0) - { - file_entries->libs[idx_old].flags = entry->flags; - /* XXX: Actually we can optimize here and remove duplicates. */ - file_entries->libs[idx_old].key = str_offset + pad; - } - if (opt_format != 0) - { - /* We could subtract file_entries_new_size from str_offset - - not doing so makes the code easier, the string table - always begins at the beginning of the new cache - struct. */ - file_entries_new->libs[idx_new].flags = entry->flags; - file_entries_new->libs[idx_new].osversion = entry->osversion; - file_entries_new->libs[idx_new].hwcap = entry->hwcap; - file_entries_new->libs[idx_new].key = str_offset; - } - - size_t len = strlen (entry->lib) + 1; - str = mempcpy (str, entry->lib, len); - str_offset += len; - /* Then the path. */ - if (opt_format != 2 && entry->hwcap == 0) - file_entries->libs[idx_old].value = str_offset + pad; - if (opt_format != 0) - file_entries_new->libs[idx_new].value = str_offset; - len = strlen (entry->path) + 1; - str = mempcpy (str, entry->path, len); - str_offset += len; - /* Ignore entries with hwcap for old format. */ - if (entry->hwcap == 0) - ++idx_old; - } - - /* Duplicate last old cache entry if needed. */ - if (opt_format != 2 - && idx_old < cache_entry_old_count) - file_entries->libs[idx_old] = file_entries->libs[idx_old - 1]; - - /* Write out the cache. */ - - /* Write cache first to a temporary file and rename it later. */ - char *temp_name = xmalloc (strlen (cache_name) + 2); - sprintf (temp_name, "%s~", cache_name); - - /* Create file. */ - int fd = open (temp_name, O_CREAT|O_WRONLY|O_TRUNC|O_NOFOLLOW, - S_IRUSR|S_IWUSR); - if (fd < 0) - error (EXIT_FAILURE, errno, _("Can't create temporary cache file %s"), - temp_name); - - /* Write contents. */ - if (opt_format != 2) - { - if (write (fd, file_entries, file_entries_size) - != (ssize_t) file_entries_size) - error (EXIT_FAILURE, errno, _("Writing of cache data failed")); - } - if (opt_format != 0) - { - /* Align cache. */ - if (opt_format != 2) - { - char zero[pad]; - memset (zero, '\0', pad); - if (write (fd, zero, pad) != (ssize_t) pad) - error (EXIT_FAILURE, errno, _("Writing of cache data failed")); - } - if (write (fd, file_entries_new, file_entries_new_size) - != (ssize_t) file_entries_new_size) - error (EXIT_FAILURE, errno, _("Writing of cache data failed")); - } - - if (write (fd, strings, total_strlen) != (ssize_t) total_strlen - || close (fd)) - error (EXIT_FAILURE, errno, _("Writing of cache data failed")); - - /* Make sure user can always read cache file */ - if (chmod (temp_name, S_IROTH|S_IRGRP|S_IRUSR|S_IWUSR)) - error (EXIT_FAILURE, errno, - _("Changing access rights of %s to %#o failed"), temp_name, - S_IROTH|S_IRGRP|S_IRUSR|S_IWUSR); - - /* Move temporary to its final location. */ - if (rename (temp_name, cache_name)) - error (EXIT_FAILURE, errno, _("Renaming of %s to %s failed"), temp_name, - cache_name); - - /* Free all allocated memory. */ - free (file_entries_new); - free (file_entries); - free (strings); - - while (entries) - { - entry = entries; - entries = entries->next; - free (entry); - } -} - - -/* Add one library to the cache. */ -void -add_to_cache (const char *path, const char *lib, int flags, - unsigned int osversion, uint64_t hwcap) -{ - size_t liblen = strlen (lib) + 1; - size_t len = liblen + strlen (path) + 1; - struct cache_entry *new_entry - = xmalloc (sizeof (struct cache_entry) + liblen + len); - - new_entry->lib = memcpy ((char *) (new_entry + 1), lib, liblen); - new_entry->path = new_entry->lib + liblen; - snprintf (new_entry->path, len, "%s/%s", path, lib); - new_entry->flags = flags; - new_entry->osversion = osversion; - new_entry->hwcap = hwcap; - new_entry->bits_hwcap = 0; - - /* Count the number of bits set in the masked value. */ - for (size_t i = 0; - (~((1ULL << i) - 1) & hwcap) != 0 && i < 8 * sizeof (hwcap); ++i) - if ((hwcap & (1ULL << i)) != 0) - ++new_entry->bits_hwcap; - - - /* Keep the list sorted - search for right place to insert. */ - struct cache_entry *ptr = entries; - struct cache_entry *prev = entries; - while (ptr != NULL) - { - if (compare (ptr, new_entry) > 0) - break; - prev = ptr; - ptr = ptr->next; - } - /* Is this the first entry? */ - if (ptr == entries) - { - new_entry->next = entries; - entries = new_entry; - } - else - { - new_entry->next = prev->next; - prev->next = new_entry; - } -} - - -/* Auxiliary cache. */ - -struct aux_cache_entry_id -{ - uint64_t ino; - uint64_t ctime; - uint64_t size; - uint64_t dev; -}; - -struct aux_cache_entry -{ - struct aux_cache_entry_id id; - int flags; - unsigned int osversion; - int used; - char *soname; - struct aux_cache_entry *next; -}; - -#define AUX_CACHEMAGIC "glibc-ld.so.auxcache-1.0" - -struct aux_cache_file_entry -{ - struct aux_cache_entry_id id; /* Unique id of entry. */ - int32_t flags; /* This is 1 for an ELF library. */ - uint32_t soname; /* String table indice. */ - uint32_t osversion; /* Required OS version. */ - int32_t pad; -}; - -/* ldconfig maintains an auxiliary cache file that allows - only reading those libraries that have changed since the last iteration. - For this for each library some information is cached in the auxiliary - cache. */ -struct aux_cache_file -{ - char magic[sizeof AUX_CACHEMAGIC - 1]; - uint32_t nlibs; /* Number of entries. */ - uint32_t len_strings; /* Size of string table. */ - struct aux_cache_file_entry libs[0]; /* Entries describing libraries. */ - /* After this the string table of size len_strings is found. */ -}; - -static const unsigned int primes[] = -{ - 1021, 2039, 4093, 8191, 16381, 32749, 65521, 131071, 262139, - 524287, 1048573, 2097143, 4194301, 8388593, 16777213, 33554393, - 67108859, 134217689, 268435399, 536870909, 1073741789, 2147483647 -}; - -static size_t aux_hash_size; -static struct aux_cache_entry **aux_hash; - -/* Simplistic hash function for aux_cache_entry_id. */ -static unsigned int -aux_cache_entry_id_hash (struct aux_cache_entry_id *id) -{ - uint64_t ret = ((id->ino * 11 + id->ctime) * 11 + id->size) * 11 + id->dev; - return ret ^ (ret >> 32); -} - -static size_t nextprime (size_t x) -{ - for (unsigned int i = 0; i < sizeof (primes) / sizeof (primes[0]); ++i) - if (primes[i] >= x) - return primes[i]; - return x; -} - -void -init_aux_cache (void) -{ - aux_hash_size = primes[3]; - aux_hash = xcalloc (aux_hash_size, sizeof (struct aux_cache_entry *)); -} - -int -search_aux_cache (struct stat64 *stat_buf, int *flags, - unsigned int *osversion, char **soname) -{ - struct aux_cache_entry_id id; - id.ino = (uint64_t) stat_buf->st_ino; - id.ctime = (uint64_t) stat_buf->st_ctime; - id.size = (uint64_t) stat_buf->st_size; - id.dev = (uint64_t) stat_buf->st_dev; - - unsigned int hash = aux_cache_entry_id_hash (&id); - struct aux_cache_entry *entry; - for (entry = aux_hash[hash % aux_hash_size]; entry; entry = entry->next) - if (id.ino == entry->id.ino - && id.ctime == entry->id.ctime - && id.size == entry->id.size - && id.dev == entry->id.dev) - { - *flags = entry->flags; - *osversion = entry->osversion; - if (entry->soname != NULL) - *soname = xstrdup (entry->soname); - else - *soname = NULL; - entry->used = 1; - return 1; - } - - return 0; -} - -static void -insert_to_aux_cache (struct aux_cache_entry_id *id, int flags, - unsigned int osversion, const char *soname, int used) -{ - size_t hash = aux_cache_entry_id_hash (id) % aux_hash_size; - struct aux_cache_entry *entry; - for (entry = aux_hash[hash]; entry; entry = entry->next) - if (id->ino == entry->id.ino - && id->ctime == entry->id.ctime - && id->size == entry->id.size - && id->dev == entry->id.dev) - abort (); - - size_t len = soname ? strlen (soname) + 1 : 0; - entry = xmalloc (sizeof (struct aux_cache_entry) + len); - entry->id = *id; - entry->flags = flags; - entry->osversion = osversion; - entry->used = used; - if (soname != NULL) - entry->soname = memcpy ((char *) (entry + 1), soname, len); - else - entry->soname = NULL; - entry->next = aux_hash[hash]; - aux_hash[hash] = entry; -} - -void -add_to_aux_cache (struct stat64 *stat_buf, int flags, - unsigned int osversion, const char *soname) -{ - struct aux_cache_entry_id id; - id.ino = (uint64_t) stat_buf->st_ino; - id.ctime = (uint64_t) stat_buf->st_ctime; - id.size = (uint64_t) stat_buf->st_size; - id.dev = (uint64_t) stat_buf->st_dev; - insert_to_aux_cache (&id, flags, osversion, soname, 1); -} - -/* Load auxiliary cache to search for unchanged entries. */ -void -load_aux_cache (const char *aux_cache_name) -{ - int fd = open (aux_cache_name, O_RDONLY); - if (fd < 0) - { - init_aux_cache (); - return; - } - - struct stat64 st; - if (fstat64 (fd, &st) < 0 || st.st_size < sizeof (struct aux_cache_file)) - { - close (fd); - init_aux_cache (); - return; - } - - size_t aux_cache_size = st.st_size; - struct aux_cache_file *aux_cache - = mmap (NULL, aux_cache_size, PROT_READ, MAP_PRIVATE, fd, 0); - 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_size != (sizeof(struct aux_cache_file) + - aux_cache->nlibs * sizeof(struct aux_cache_file_entry) + - aux_cache->len_strings)) - { - close (fd); - init_aux_cache (); - return; - } - - aux_hash_size = nextprime (aux_cache->nlibs); - aux_hash = xcalloc (aux_hash_size, sizeof (struct aux_cache_entry *)); - - const char *aux_cache_data - = (const char *) &aux_cache->libs[aux_cache->nlibs]; - for (unsigned int i = 0; i < aux_cache->nlibs; ++i) - insert_to_aux_cache (&aux_cache->libs[i].id, - aux_cache->libs[i].flags, - aux_cache->libs[i].osversion, - aux_cache->libs[i].soname == 0 - ? NULL : aux_cache_data + aux_cache->libs[i].soname, - 0); - - munmap (aux_cache, aux_cache_size); - close (fd); -} - -/* Save the contents of the auxiliary cache. */ -void -save_aux_cache (const char *aux_cache_name) -{ - /* Count the length of all sonames. We start with empty string. */ - size_t total_strlen = 1; - /* Number of cache entries. */ - int cache_entry_count = 0; - - for (size_t i = 0; i < aux_hash_size; ++i) - for (struct aux_cache_entry *entry = aux_hash[i]; - entry != NULL; entry = entry->next) - if (entry->used) - { - ++cache_entry_count; - if (entry->soname != NULL) - total_strlen += strlen (entry->soname) + 1; - } - - /* Auxiliary cache. */ - size_t file_entries_size - = sizeof (struct aux_cache_file) - + cache_entry_count * sizeof (struct aux_cache_file_entry); - struct aux_cache_file *file_entries - = xmalloc (file_entries_size + total_strlen); - - /* Fill in the header of the auxiliary cache. */ - memset (file_entries, '\0', sizeof (struct aux_cache_file)); - memcpy (file_entries->magic, AUX_CACHEMAGIC, sizeof AUX_CACHEMAGIC - 1); - - file_entries->nlibs = cache_entry_count; - file_entries->len_strings = total_strlen; - - /* Initial String offset for auxiliary cache is always after the - special empty string. */ - unsigned int str_offset = 1; - - /* An array for all strings. */ - char *str = (char *) file_entries + file_entries_size; - *str++ = '\0'; - - size_t idx = 0; - for (size_t i = 0; i < aux_hash_size; ++i) - for (struct aux_cache_entry *entry = aux_hash[i]; - entry != NULL; entry = entry->next) - if (entry->used) - { - file_entries->libs[idx].id = entry->id; - file_entries->libs[idx].flags = entry->flags; - if (entry->soname == NULL) - file_entries->libs[idx].soname = 0; - else - { - file_entries->libs[idx].soname = str_offset; - - size_t len = strlen (entry->soname) + 1; - str = mempcpy (str, entry->soname, len); - str_offset += len; - } - file_entries->libs[idx].osversion = entry->osversion; - file_entries->libs[idx++].pad = 0; - } - - /* Write out auxiliary cache file. */ - /* Write auxiliary cache first to a temporary file and rename it later. */ - - char *temp_name = xmalloc (strlen (aux_cache_name) + 2); - sprintf (temp_name, "%s~", aux_cache_name); - - /* Check that directory exists and create if needed. */ - char *dir = strdupa (aux_cache_name); - dir = dirname (dir); - - struct stat64 st; - if (stat64 (dir, &st) < 0) - { - if (mkdir (dir, 0700) < 0) - goto out_fail; - } - - /* Create file. */ - int fd = open (temp_name, O_CREAT|O_WRONLY|O_TRUNC|O_NOFOLLOW, - S_IRUSR|S_IWUSR); - if (fd < 0) - goto out_fail; - - if (write (fd, file_entries, file_entries_size + total_strlen) - != (ssize_t) (file_entries_size + total_strlen) - || close (fd)) - { - unlink (temp_name); - goto out_fail; - } - - /* Move temporary to its final location. */ - if (rename (temp_name, aux_cache_name)) - unlink (temp_name); - -out_fail: - /* Free allocated memory. */ - free (temp_name); - free (file_entries); -} diff --git a/elf/chroot_canon.c b/elf/chroot_canon.c deleted file mode 100644 index 78cd6f4a5e..0000000000 --- a/elf/chroot_canon.c +++ /dev/null @@ -1,177 +0,0 @@ -/* Return the canonical absolute name of a given file inside chroot. - Copyright (C) 1996-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, see <http://www.gnu.org/licenses/>. */ - -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <limits.h> -#include <sys/stat.h> -#include <errno.h> -#include <stddef.h> -#include <stdint.h> - -#include <eloop-threshold.h> -#include <ldconfig.h> - -#ifndef PATH_MAX -#define PATH_MAX 1024 -#endif - -/* Return the canonical absolute name of file NAME as if chroot(CHROOT) was - done first. A canonical name does not contain any `.', `..' components - nor any repeated path separators ('/') or symlinks. All path components - must exist and NAME must be absolute filename. The result is malloc'd. - The returned name includes the CHROOT prefix. */ - -char * -chroot_canon (const char *chroot, const char *name) -{ - char *rpath; - char *dest; - char *extra_buf = NULL; - char *rpath_root; - const char *start; - const char *end; - const char *rpath_limit; - int num_links = 0; - size_t chroot_len = strlen (chroot); - - if (chroot_len < 1) - { - __set_errno (EINVAL); - return NULL; - } - - rpath = xmalloc (chroot_len + PATH_MAX); - - rpath_limit = rpath + chroot_len + PATH_MAX; - - rpath_root = (char *) mempcpy (rpath, chroot, chroot_len) - 1; - if (*rpath_root != '/') - *++rpath_root = '/'; - dest = rpath_root + 1; - - for (start = end = name; *start; start = end) - { - struct stat64 st; - - /* Skip sequence of multiple path-separators. */ - while (*start == '/') - ++start; - - /* Find end of path component. */ - for (end = start; *end && *end != '/'; ++end) - /* Nothing. */; - - if (end - start == 0) - break; - else if (end - start == 1 && start[0] == '.') - /* nothing */; - else if (end - start == 2 && start[0] == '.' && start[1] == '.') - { - /* Back up to previous component, ignore if at root already. */ - if (dest > rpath_root + 1) - while ((--dest)[-1] != '/'); - } - else - { - size_t new_size; - - if (dest[-1] != '/') - *dest++ = '/'; - - if (dest + (end - start) >= rpath_limit) - { - ptrdiff_t dest_offset = dest - rpath; - char *new_rpath; - - new_size = rpath_limit - rpath; - if (end - start + 1 > PATH_MAX) - new_size += end - start + 1; - else - new_size += PATH_MAX; - new_rpath = (char *) xrealloc (rpath, new_size); - rpath = new_rpath; - rpath_limit = rpath + new_size; - - dest = rpath + dest_offset; - } - - dest = mempcpy (dest, start, end - start); - *dest = '\0'; - - if (lstat64 (rpath, &st) < 0) - { - if (*end == '\0') - goto done; - goto error; - } - - if (S_ISLNK (st.st_mode)) - { - char *buf = alloca (PATH_MAX); - size_t len; - - if (++num_links > __eloop_threshold ()) - { - __set_errno (ELOOP); - goto error; - } - - ssize_t n = readlink (rpath, buf, PATH_MAX - 1); - if (n < 0) - { - if (*end == '\0') - goto done; - goto error; - } - buf[n] = '\0'; - - if (!extra_buf) - extra_buf = alloca (PATH_MAX); - - len = strlen (end); - if (len >= PATH_MAX - n) - { - __set_errno (ENAMETOOLONG); - goto error; - } - - /* Careful here, end may be a pointer into extra_buf... */ - memmove (&extra_buf[n], end, len + 1); - name = end = memcpy (extra_buf, buf, n); - - if (buf[0] == '/') - dest = rpath_root + 1; /* It's an absolute symlink */ - else - /* Back up to previous component, ignore if at root already: */ - if (dest > rpath_root + 1) - while ((--dest)[-1] != '/'); - } - } - } - done: - if (dest > rpath_root + 1 && dest[-1] == '/') - --dest; - *dest = '\0'; - - return rpath; - - error: - free (rpath); - return NULL; -} diff --git a/elf/circleload1.c b/elf/circleload1.c deleted file mode 100644 index 990ff84a84..0000000000 --- a/elf/circleload1.c +++ /dev/null @@ -1,166 +0,0 @@ -#include <dlfcn.h> -#include <libintl.h> -#include <link.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#define MAPS ((struct link_map *) _r_debug.r_map) - -static int -check_loaded_objects (const char **loaded) -{ - struct link_map *lm; - int n; - int *found = NULL; - int errors = 0; - - for (n = 0; loaded[n]; n++) - /* NOTHING */; - - if (n) - { - found = (int *) alloca (sizeof (int) * n); - memset (found, 0, sizeof (int) * n); - } - - printf(" Name\n"); - printf(" --------------------------------------------------------\n"); - for (lm = MAPS; lm; lm = lm->l_next) - { - if (lm->l_name && lm->l_name[0]) - printf(" %s, count = %d\n", lm->l_name, (int) lm->l_direct_opencount); - if (lm->l_type == lt_loaded && lm->l_name) - { - int match = 0; - for (n = 0; loaded[n] != NULL; n++) - { - if (strcmp (basename (loaded[n]), basename (lm->l_name)) == 0) - { - found[n] = 1; - match = 1; - break; - } - } - - if (match == 0) - { - ++errors; - printf ("ERRORS: %s is not unloaded\n", lm->l_name); - } - } - } - - for (n = 0; loaded[n] != NULL; n++) - { - if (found[n] == 0) - { - ++errors; - printf ("ERRORS: %s is not loaded\n", loaded[n]); - } - } - - return errors; -} - -static int -load_dso (const char **loading, int undef, int flag) -{ - void *obj; - const char *loaded[] = { NULL, NULL, NULL, NULL }; - int errors = 0; - const char *errstring; - - printf ("\nThis is what is in memory now:\n"); - errors += check_loaded_objects (loaded); - - printf ("Loading shared object %s: %s\n", loading[0], - flag == RTLD_LAZY ? "RTLD_LAZY" : "RTLD_NOW"); - obj = dlopen (loading[0], flag); - if (obj == NULL) - { - if (flag == RTLD_LAZY) - { - ++errors; - printf ("ERRORS: dlopen shouldn't fail for RTLD_LAZY\n"); - } - - errstring = dlerror (); - if (strstr (errstring, "undefined symbol") == 0 - || strstr (errstring, "circlemod2_undefined") == 0) - { - ++errors; - printf ("ERRORS: dlopen: `%s': Invalid error string\n", - errstring); - } - else - printf ("dlopen: %s\n", errstring); - } - else - { - if (undef && flag == RTLD_NOW) - { - ++errors; - printf ("ERRORS: dlopen shouldn't work for RTLD_NOW\n"); - } - - if (!undef) - { - int (*func) (void); - - func = dlsym (obj, "circlemod1"); - if (func == NULL) - { - ++errors; - printf ("ERRORS: cannot get address of \"circlemod1\": %s\n", - dlerror ()); - } - else if (func () != 3) - { - ++errors; - printf ("ERRORS: function \"circlemod1\" returned wrong result\n"); - } - } - - loaded[0] = loading[0]; - loaded[1] = loading[1]; - loaded[2] = loading[2]; - } - errors += check_loaded_objects (loaded); - - if (obj) - { - printf ("UnLoading shared object %s\n", loading[0]); - dlclose (obj); - loaded[0] = NULL; - loaded[1] = NULL; - loaded[2] = NULL; - errors += check_loaded_objects (loaded); - } - - return errors; -} - -int -main (void) -{ - int errors = 0; - const char *loading[3]; - - loading[0] = "circlemod1a.so"; - loading[1] = "circlemod2a.so"; - loading[2] = "circlemod3a.so"; - errors += load_dso (loading, 0, RTLD_LAZY); - errors += load_dso (loading, 0, RTLD_NOW); - - loading[0] = "circlemod1.so"; - loading[1] = "circlemod2.so"; - loading[2] = "circlemod3.so"; - errors += load_dso (loading, 1, RTLD_LAZY); - errors += load_dso (loading, 1, RTLD_NOW); - - if (errors != 0) - printf ("%d errors found\n", errors); - - return errors; -} diff --git a/elf/circlemod1.c b/elf/circlemod1.c deleted file mode 100644 index 933ccd3c02..0000000000 --- a/elf/circlemod1.c +++ /dev/null @@ -1,7 +0,0 @@ -extern int circlemod2 (void); - -int -circlemod1 (void) -{ - return circlemod2 (); -} diff --git a/elf/circlemod1a.c b/elf/circlemod1a.c deleted file mode 100644 index 45f229136d..0000000000 --- a/elf/circlemod1a.c +++ /dev/null @@ -1 +0,0 @@ -#include "circlemod1.c" diff --git a/elf/circlemod2.c b/elf/circlemod2.c deleted file mode 100644 index ed8c1175fb..0000000000 --- a/elf/circlemod2.c +++ /dev/null @@ -1,9 +0,0 @@ -extern void circlemod2_undefined (void); -extern int circlemod3 (void); - -int -circlemod2 (void) -{ - circlemod2_undefined (); - return circlemod3 (); -} diff --git a/elf/circlemod2a.c b/elf/circlemod2a.c deleted file mode 100644 index dc6410b28b..0000000000 --- a/elf/circlemod2a.c +++ /dev/null @@ -1,7 +0,0 @@ -extern int circlemod3 (void); - -int -circlemod2 (void) -{ - return circlemod3 (); -} diff --git a/elf/circlemod3.c b/elf/circlemod3.c deleted file mode 100644 index 8d16fe682f..0000000000 --- a/elf/circlemod3.c +++ /dev/null @@ -1,14 +0,0 @@ -extern int circlemod1 (void); -extern int circlemod2 (void); - -int -circlemod3 (void) -{ - return 3; -} - -int -circlemod3a (void) -{ - return circlemod1 () + circlemod2 (); -} diff --git a/elf/circlemod3a.c b/elf/circlemod3a.c deleted file mode 100644 index f1b166ef84..0000000000 --- a/elf/circlemod3a.c +++ /dev/null @@ -1 +0,0 @@ -#include "circlemod3.c" diff --git a/elf/constload1.c b/elf/constload1.c deleted file mode 100644 index 7381beea88..0000000000 --- a/elf/constload1.c +++ /dev/null @@ -1,32 +0,0 @@ -#include <dlfcn.h> -#include <errno.h> -#include <error.h> -#include <mcheck.h> -#include <stdio.h> -#include <stdlib.h> - -int -main (void) -{ - int (*foo) (void); - void *h; - int ret; - - mtrace (); - - h = dlopen ("constload2.so", RTLD_LAZY | RTLD_GLOBAL); - if (h == NULL) - error (EXIT_FAILURE, errno, "cannot load module \"constload2.so\""); - foo = dlsym (h, "foo"); - ret = foo (); - /* Note that the following dlclose() call cannot unload the objects. - Due to the introduced relocation dependency constload2.so depends - on constload3.so and the dependencies of constload2.so on constload3.so - is not visible to ld.so since it's done using dlopen(). */ - if (dlclose (h) != 0) - { - puts ("failed to close"); - exit (EXIT_FAILURE); - } - return ret; -} diff --git a/elf/constload2.c b/elf/constload2.c deleted file mode 100644 index bf1bf182f3..0000000000 --- a/elf/constload2.c +++ /dev/null @@ -1,50 +0,0 @@ -#include <dlfcn.h> -#include <stdio.h> -#include <stdlib.h> - -extern int bar (void); -extern int baz (void); -extern int foo (void); -extern void __attribute__ ((__constructor__)) init (void); - -void *h; - -int -foo (void) -{ - return 42 + bar (); -} - -int -baz (void) -{ - return -21; -} - - -void -__attribute__ ((__constructor__)) -init (void) -{ - h = dlopen ("constload3.so", RTLD_GLOBAL | RTLD_LAZY); - if (h == NULL) - { - puts ("failed to load constload3"); - exit (1); - } - else - puts ("succeeded loading constload3"); -} - -static void -__attribute__ ((__destructor__)) -fini (void) -{ - if (dlclose (h) != 0) - { - puts ("failed to unload constload3"); - exit (1); - } - else - puts ("succeeded unloading constload3"); -} diff --git a/elf/constload3.c b/elf/constload3.c deleted file mode 100644 index 9c37620bba..0000000000 --- a/elf/constload3.c +++ /dev/null @@ -1,8 +0,0 @@ -extern int baz (void); -extern int bar (void); - -int -bar (void) -{ - return -21 + baz (); -} diff --git a/elf/dblload.c b/elf/dblload.c deleted file mode 100644 index 52389a60ce..0000000000 --- a/elf/dblload.c +++ /dev/null @@ -1,53 +0,0 @@ -#include <dlfcn.h> -#include <mcheck.h> -#include <stdio.h> -#include <stdlib.h> - - -int -main (void) -{ - void *p1; - void *p2; - int (*fp) (void); - int result; - - mtrace (); - - p1 = dlopen ("dblloadmod1.so", RTLD_LAZY); - if (p1 == NULL) - { - printf ("cannot open dblloadmod1.so: %s\n", dlerror ()); - exit (EXIT_FAILURE); - } - - p2 = dlopen ("dblloadmod2.so", RTLD_LAZY); - if (p1 == NULL) - { - printf ("cannot open dblloadmod2.so: %s\n", dlerror ()); - exit (EXIT_FAILURE); - } - - fp = dlsym (p1, "foo"); - if (fp == NULL) - { - printf ("cannot get function \"foo\": %s\n", dlerror ()); - exit (EXIT_FAILURE); - } - - result = fp (); - - if (dlclose (p1) != 0) - { - printf ("error while closing dblloadmod1.so: %s\n", dlerror ()); - exit (EXIT_FAILURE); - } - - if (dlclose (p2) != 0) - { - printf ("error while closing dblloadmod2.so: %s\n", dlerror ()); - exit (EXIT_FAILURE); - } - - return result; -} diff --git a/elf/dblloadmod1.c b/elf/dblloadmod1.c deleted file mode 100644 index ecec29ec63..0000000000 --- a/elf/dblloadmod1.c +++ /dev/null @@ -1,8 +0,0 @@ -extern int bar (void); -extern int foo (void); - -int -foo (void) -{ - return 10 + bar (); -} diff --git a/elf/dblloadmod2.c b/elf/dblloadmod2.c deleted file mode 100644 index 3e20aa941b..0000000000 --- a/elf/dblloadmod2.c +++ /dev/null @@ -1,15 +0,0 @@ -extern int bar (void); -extern int baz (void); -extern int xyzzy (void); - -int -baz (void) -{ - return -42; -} - -int -xyzzy (void) -{ - return 10 + bar (); -} diff --git a/elf/dblloadmod3.c b/elf/dblloadmod3.c deleted file mode 100644 index 80ac3a6375..0000000000 --- a/elf/dblloadmod3.c +++ /dev/null @@ -1,8 +0,0 @@ -extern int bar (void); -extern int baz (void); - -int -bar (void) -{ - return 32 + baz (); -} diff --git a/elf/dblunload.c b/elf/dblunload.c deleted file mode 100644 index ab0b2a5e9e..0000000000 --- a/elf/dblunload.c +++ /dev/null @@ -1,53 +0,0 @@ -#include <dlfcn.h> -#include <mcheck.h> -#include <stdio.h> -#include <stdlib.h> - - -int -main (void) -{ - void *p1; - void *p2; - int (*fp) (void); - int result; - - mtrace (); - - p1 = dlopen ("dblloadmod1.so", RTLD_LAZY); - if (p1 == NULL) - { - printf ("cannot load dblloadmod1.so: %s\n", dlerror ()); - exit (EXIT_FAILURE); - } - - p2 = dlopen ("dblloadmod2.so", RTLD_LAZY); - if (p2 == NULL) - { - printf ("cannot load dblloadmod2.so: %s\n", dlerror ()); - exit (EXIT_FAILURE); - } - - if (dlclose (p1) != 0) - { - printf ("error while closing dblloadmod1.so: %s\n", dlerror ()); - exit (EXIT_FAILURE); - } - - fp = dlsym (p2, "xyzzy"); - if (fp == NULL) - { - printf ("cannot get function \"xyzzy\": %s\n", dlerror ()); - exit (EXIT_FAILURE); - } - - result = fp (); - - if (dlclose (p2) != 0) - { - printf ("error while closing dblloadmod2.so: %s\n", dlerror ()); - exit (EXIT_FAILURE); - } - - return result; -} diff --git a/elf/dep1.c b/elf/dep1.c deleted file mode 100644 index 7ef47adb43..0000000000 --- a/elf/dep1.c +++ /dev/null @@ -1,25 +0,0 @@ -#include <unistd.h> - -extern int dep1 (void); -extern int dep2 (void); -extern int dep4 (void); - -static void -__attribute__ ((constructor)) -init (void) -{ - write (1, "3", 1); -} - -static void -__attribute__ ((destructor)) -fini (void) -{ - write (1, "6", 1); -} - -int -dep1 (void) -{ - return dep4 () - dep2 (); -} diff --git a/elf/dep2.c b/elf/dep2.c deleted file mode 100644 index 749036a4ec..0000000000 --- a/elf/dep2.c +++ /dev/null @@ -1,25 +0,0 @@ -#include <unistd.h> - -extern int dep2 (void); -extern int dep3 (void); -extern int dep4 (void); - -static void -__attribute__ ((constructor)) -init (void) -{ - write (1, "2", 1); -} - -static void -__attribute__ ((destructor)) -fini (void) -{ - write (1, "7", 1); -} - -int -dep2 (void) -{ - return dep3 () - dep4 (); -} diff --git a/elf/dep3.c b/elf/dep3.c deleted file mode 100644 index 3df6282009..0000000000 --- a/elf/dep3.c +++ /dev/null @@ -1,23 +0,0 @@ -#include <unistd.h> - -extern int dep3 (void); - -static void -__attribute__ ((constructor)) -init (void) -{ - write (1, "0", 1); -} - -static void -__attribute__ ((destructor)) -fini (void) -{ - write (1, "9\n", 2); -} - -int -dep3 (void) -{ - return 42; -} diff --git a/elf/dep4.c b/elf/dep4.c deleted file mode 100644 index c496d6f531..0000000000 --- a/elf/dep4.c +++ /dev/null @@ -1,24 +0,0 @@ -#include <unistd.h> - -extern int dep3 (void); -extern int dep4 (void); - -static void -__attribute__ ((constructor)) -init (void) -{ - write (1, "1", 1); -} - -static void -__attribute__ ((destructor)) -fini (void) -{ - write (1, "8", 1); -} - -int -dep4 (void) -{ - return dep3 (); -} diff --git a/elf/dl-addr-obj.c b/elf/dl-addr-obj.c deleted file mode 100644 index 62aa630ce5..0000000000 --- a/elf/dl-addr-obj.c +++ /dev/null @@ -1,75 +0,0 @@ -/* Determine if address is inside object load segments. - Copyright (C) 1996-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -#include <link.h> -#include <elf.h> - -/* Return non-zero if ADDR lies within one of L's loadable segments. - We have three cases we care about. - - Case 1: addr is above a segment. - +==================+<- l_map_end - | |<- addr - |------------------|<- l_addr + p_vaddr + p_memsz - | | - | | - |------------------|<- l_addr + p_vaddr - |------------------|<- l_addr - | | - +==================+<- l_map_start - - Case 2: addr is within a segments. - +==================+<- l_map_end - | | - |------------------|<- l_addr + p_vaddr + p_memsz - | |<- addr - | | - |------------------|<- l_addr + p_vaddr - |------------------|<- l_addr - | | - +==================+<- l_map_start - - Case 3: addr is below a segments. - +==================+<- l_map_end - | | - |------------------|<- l_addr + p_vaddr + p_memsz - | | - | | - |------------------|<- l_addr + p_vaddr - |------------------|<- l_addr - | |<- addr - +==================+<- l_map_start - - All the arithmetic is unsigned and we shift all the values down by - l_addr + p_vaddr and then compare the normalized addr to the range - of interest i.e. 0 <= addr < p_memsz. - -*/ -int -internal_function -_dl_addr_inside_object (struct link_map *l, const ElfW(Addr) addr) -{ - int n = l->l_phnum; - const ElfW(Addr) reladdr = addr - l->l_addr; - - while (--n >= 0) - if (l->l_phdr[n].p_type == PT_LOAD - && reladdr - l->l_phdr[n].p_vaddr < l->l_phdr[n].p_memsz) - return 1; - return 0; -} diff --git a/elf/dl-addr.c b/elf/dl-addr.c deleted file mode 100644 index 1fac63d1a9..0000000000 --- a/elf/dl-addr.c +++ /dev/null @@ -1,146 +0,0 @@ -/* Locate the shared object symbol nearest a given address. - Copyright (C) 1996-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -#include <dlfcn.h> -#include <stddef.h> -#include <ldsodefs.h> - - -static inline void -__attribute ((always_inline)) -determine_info (const ElfW(Addr) addr, struct link_map *match, Dl_info *info, - struct link_map **mapp, const ElfW(Sym) **symbolp) -{ - /* Now we know what object the address lies in. */ - info->dli_fname = match->l_name; - info->dli_fbase = (void *) match->l_map_start; - - /* If this is the main program the information is incomplete. */ - if (__builtin_expect (match->l_name[0], 'a') == '\0' - && match->l_type == lt_executable) - info->dli_fname = _dl_argv[0]; - - const ElfW(Sym) *symtab - = (const ElfW(Sym) *) D_PTR (match, l_info[DT_SYMTAB]); - const char *strtab = (const char *) D_PTR (match, l_info[DT_STRTAB]); - - ElfW(Word) strtabsize = match->l_info[DT_STRSZ]->d_un.d_val; - - const ElfW(Sym) *matchsym = NULL; - if (match->l_info[DT_ADDRTAGIDX (DT_GNU_HASH) + DT_NUM + DT_THISPROCNUM - + DT_VERSIONTAGNUM + DT_EXTRANUM + DT_VALNUM] != NULL) - { - /* We look at all symbol table entries referenced by the hash - table. */ - for (Elf_Symndx bucket = 0; bucket < match->l_nbuckets; ++bucket) - { - Elf32_Word symndx = match->l_gnu_buckets[bucket]; - if (symndx != 0) - { - const Elf32_Word *hasharr = &match->l_gnu_chain_zero[symndx]; - - do - { - /* The hash table never references local symbols so - we can omit that test here. */ - if ((symtab[symndx].st_shndx != SHN_UNDEF - || symtab[symndx].st_value != 0) - && ELFW(ST_TYPE) (symtab[symndx].st_info) != STT_TLS - && DL_ADDR_SYM_MATCH (match, &symtab[symndx], - matchsym, addr) - && symtab[symndx].st_name < strtabsize) - matchsym = (ElfW(Sym) *) &symtab[symndx]; - - ++symndx; - } - while ((*hasharr++ & 1u) == 0); - } - } - } - else - { - const ElfW(Sym) *symtabend; - if (match->l_info[DT_HASH] != NULL) - symtabend = (symtab - + ((Elf_Symndx *) D_PTR (match, l_info[DT_HASH]))[1]); - else - /* There is no direct way to determine the number of symbols in the - dynamic symbol table and no hash table is present. The ELF - binary is ill-formed but what shall we do? Use the beginning of - the string table which generally follows the symbol table. */ - symtabend = (const ElfW(Sym) *) strtab; - - for (; (void *) symtab < (void *) symtabend; ++symtab) - if ((ELFW(ST_BIND) (symtab->st_info) == STB_GLOBAL - || ELFW(ST_BIND) (symtab->st_info) == STB_WEAK) - && __glibc_likely (!dl_symbol_visibility_binds_local_p (symtab)) - && ELFW(ST_TYPE) (symtab->st_info) != STT_TLS - && (symtab->st_shndx != SHN_UNDEF - || symtab->st_value != 0) - && DL_ADDR_SYM_MATCH (match, symtab, matchsym, addr) - && symtab->st_name < strtabsize) - matchsym = (ElfW(Sym) *) symtab; - } - - if (mapp) - *mapp = match; - if (symbolp) - *symbolp = matchsym; - - if (matchsym) - { - /* We found a symbol close by. Fill in its name and exact - address. */ - lookup_t matchl = LOOKUP_VALUE (match); - - info->dli_sname = strtab + matchsym->st_name; - info->dli_saddr = DL_SYMBOL_ADDRESS (matchl, matchsym); - } - else - { - /* No symbol matches. We return only the containing object. */ - info->dli_sname = NULL; - info->dli_saddr = NULL; - } -} - - -int -internal_function -_dl_addr (const void *address, Dl_info *info, - struct link_map **mapp, const ElfW(Sym) **symbolp) -{ - const ElfW(Addr) addr = DL_LOOKUP_ADDRESS (address); - int result = 0; - - /* Protect against concurrent loads and unloads. */ - __rtld_lock_lock_recursive (GL(dl_load_lock)); - - struct link_map *l = _dl_find_dso_for_object (addr); - - if (l) - { - determine_info (addr, l, info, mapp, symbolp); - result = 1; - } - - __rtld_lock_unlock_recursive (GL(dl_load_lock)); - - return result; -} -libc_hidden_def (_dl_addr) diff --git a/elf/dl-brk.c b/elf/dl-brk.c deleted file mode 100644 index c37cdfec33..0000000000 --- a/elf/dl-brk.c +++ /dev/null @@ -1,5 +0,0 @@ -/* We can use the normal code but we also know the __curbrk is not exported - from ld.so. */ -extern void *__curbrk attribute_hidden; - -#include <brk.c> diff --git a/elf/dl-cache.c b/elf/dl-cache.c deleted file mode 100644 index e9632da0b3..0000000000 --- a/elf/dl-cache.c +++ /dev/null @@ -1,325 +0,0 @@ -/* Support for reading /etc/ld.so.cache files written by Linux ldconfig. - Copyright (C) 1996-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -#include <assert.h> -#include <unistd.h> -#include <ldsodefs.h> -#include <sys/mman.h> -#include <dl-cache.h> -#include <dl-procinfo.h> -#include <stdint.h> -#include <_itoa.h> -#include <dl-hwcaps.h> - -#ifndef _DL_PLATFORMS_COUNT -# define _DL_PLATFORMS_COUNT 0 -#endif - -/* This is the starting address and the size of the mmap()ed file. */ -static struct cache_file *cache; -static struct cache_file_new *cache_new; -static size_t cachesize; - -/* 1 if cache_data + PTR points into the cache. */ -#define _dl_cache_verify_ptr(ptr) (ptr < cache_data_size) - -#define SEARCH_CACHE(cache) \ -/* We use binary search since the table is sorted in the cache file. \ - The first matching entry in the table is returned. \ - It is important to use the same algorithm as used while generating \ - the cache file. */ \ -do \ - { \ - left = 0; \ - right = cache->nlibs - 1; \ - \ - while (left <= right) \ - { \ - __typeof__ (cache->libs[0].key) key; \ - \ - middle = (left + right) / 2; \ - \ - key = cache->libs[middle].key; \ - \ - /* Make sure string table indices are not bogus before using \ - them. */ \ - if (! _dl_cache_verify_ptr (key)) \ - { \ - cmpres = 1; \ - break; \ - } \ - \ - /* Actually compare the entry with the key. */ \ - cmpres = _dl_cache_libcmp (name, cache_data + key); \ - if (__glibc_unlikely (cmpres == 0)) \ - { \ - /* Found it. LEFT now marks the last entry for which we \ - know the name is correct. */ \ - left = middle; \ - \ - /* There might be entries with this name before the one we \ - found. So we have to find the beginning. */ \ - while (middle > 0) \ - { \ - __typeof__ (cache->libs[0].key) key; \ - \ - key = cache->libs[middle - 1].key; \ - /* Make sure string table indices are not bogus before \ - using them. */ \ - if (! _dl_cache_verify_ptr (key) \ - /* Actually compare the entry. */ \ - || _dl_cache_libcmp (name, cache_data + key) != 0) \ - break; \ - --middle; \ - } \ - \ - do \ - { \ - int flags; \ - __typeof__ (cache->libs[0]) *lib = &cache->libs[middle]; \ - \ - /* Only perform the name test if necessary. */ \ - if (middle > left \ - /* We haven't seen this string so far. Test whether the \ - index is ok and whether the name matches. Otherwise \ - we are done. */ \ - && (! _dl_cache_verify_ptr (lib->key) \ - || (_dl_cache_libcmp (name, cache_data + lib->key) \ - != 0))) \ - break; \ - \ - flags = lib->flags; \ - if (_dl_cache_check_flags (flags) \ - && _dl_cache_verify_ptr (lib->value)) \ - { \ - if (best == NULL || flags == GLRO(dl_correct_cache_id)) \ - { \ - HWCAP_CHECK; \ - best = cache_data + lib->value; \ - \ - if (flags == GLRO(dl_correct_cache_id)) \ - /* We've found an exact match for the shared \ - object and no general `ELF' release. Stop \ - searching. */ \ - break; \ - } \ - } \ - } \ - while (++middle <= right); \ - break; \ - } \ - \ - if (cmpres < 0) \ - left = middle + 1; \ - else \ - right = middle - 1; \ - } \ - } \ -while (0) - - -int -internal_function -_dl_cache_libcmp (const char *p1, const char *p2) -{ - while (*p1 != '\0') - { - if (*p1 >= '0' && *p1 <= '9') - { - if (*p2 >= '0' && *p2 <= '9') - { - /* Must compare this numerically. */ - int val1; - int val2; - - val1 = *p1++ - '0'; - val2 = *p2++ - '0'; - while (*p1 >= '0' && *p1 <= '9') - val1 = val1 * 10 + *p1++ - '0'; - while (*p2 >= '0' && *p2 <= '9') - val2 = val2 * 10 + *p2++ - '0'; - if (val1 != val2) - return val1 - val2; - } - else - return 1; - } - else if (*p2 >= '0' && *p2 <= '9') - return -1; - else if (*p1 != *p2) - return *p1 - *p2; - else - { - ++p1; - ++p2; - } - } - return *p1 - *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. - 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) -{ - int left, right, middle; - int cmpres; - const char *cache_data; - uint32_t cache_data_size; - const char *best; - - /* Print a message if the loading of libs is traced. */ - if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_LIBS)) - _dl_debug_printf (" search cache=%s\n", LD_SO_CACHE); - - if (cache == NULL) - { - /* Read the contents of the file. */ - void *file = _dl_sysdep_read_whole_file (LD_SO_CACHE, &cachesize, - PROT_READ); - - /* We can handle three different cache file formats here: - - the old libc5/glibc2.0/2.1 format - - the old format with the new format in it - - only the new format - The following checks if the cache contains any of these formats. */ - if (file != MAP_FAILED && cachesize > sizeof *cache - && memcmp (file, CACHEMAGIC, sizeof CACHEMAGIC - 1) == 0) - { - size_t offset; - /* Looks ok. */ - cache = file; - - /* Check for new version. */ - offset = ALIGN_CACHE (sizeof (struct cache_file) - + cache->nlibs * sizeof (struct file_entry)); - - cache_new = (struct cache_file_new *) ((void *) cache + offset); - if (cachesize < (offset + sizeof (struct cache_file_new)) - || memcmp (cache_new->magic, CACHEMAGIC_VERSION_NEW, - sizeof CACHEMAGIC_VERSION_NEW - 1) != 0) - cache_new = (void *) -1; - } - else if (file != MAP_FAILED && cachesize > sizeof *cache_new - && memcmp (file, CACHEMAGIC_VERSION_NEW, - sizeof CACHEMAGIC_VERSION_NEW - 1) == 0) - { - cache_new = file; - cache = file; - } - else - { - if (file != MAP_FAILED) - __munmap (file, cachesize); - cache = (void *) -1; - } - - assert (cache != NULL); - } - - if (cache == (void *) -1) - /* Previously looked for the cache file and didn't find it. */ - return NULL; - - best = NULL; - - if (cache_new != (void *) -1) - { - uint64_t platform; - - /* This is where the strings start. */ - cache_data = (const char *) cache_new; - - /* Now we can compute how large the string table is. */ - cache_data_size = (const char *) cache + cachesize - cache_data; - - platform = _dl_string_platform (GLRO(dl_platform)); - if (platform != (uint64_t) -1) - platform = 1ULL << platform; - - uint64_t hwcap_mask = GET_HWCAP_MASK(); - -#define _DL_HWCAP_TLS_MASK (1LL << 63) - uint64_t hwcap_exclude = ~((GLRO(dl_hwcap) & hwcap_mask) - | _DL_HWCAP_PLATFORM | _DL_HWCAP_TLS_MASK); - - /* Only accept hwcap if it's for the right platform. */ -#define HWCAP_CHECK \ - if (lib->hwcap & hwcap_exclude) \ - continue; \ - if (GLRO(dl_osversion) && lib->osversion > GLRO(dl_osversion)) \ - continue; \ - if (_DL_PLATFORMS_COUNT \ - && (lib->hwcap & _DL_HWCAP_PLATFORM) != 0 \ - && (lib->hwcap & _DL_HWCAP_PLATFORM) != platform) \ - continue - SEARCH_CACHE (cache_new); - } - else - { - /* This is where the strings start. */ - cache_data = (const char *) &cache->libs[cache->nlibs]; - - /* Now we can compute how large the string table is. */ - cache_data_size = (const char *) cache + cachesize - cache_data; - -#undef HWCAP_CHECK -#define HWCAP_CHECK do {} while (0) - SEARCH_CACHE (cache); - } - - /* Print our result if wanted. */ - if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_LIBS, 0) - && best != NULL) - _dl_debug_printf (" trying file=%s\n", 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 -/* If the system does not support MAP_COPY we cannot leave the file open - all the time since this would create problems when the file is replaced. - Therefore we provide this function to close the file and open it again - once needed. */ -void -_dl_unload_cache (void) -{ - if (cache != NULL && cache != (struct cache_file *) -1) - { - __munmap (cache, cachesize); - cache = NULL; - } -} -#endif diff --git a/elf/dl-caller.c b/elf/dl-caller.c deleted file mode 100644 index b4c5335baa..0000000000 --- a/elf/dl-caller.c +++ /dev/null @@ -1,86 +0,0 @@ -/* Check whether caller comes from the right place. - Copyright (C) 2004-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -#include <assert.h> -#include <ldsodefs.h> -#include <stddef.h> -#include <caller.h> -#include <gnu/lib-names.h> - - -int -attribute_hidden -_dl_check_caller (const void *caller, enum allowmask mask) -{ - static const char expected1[] = LIBC_SO; - static const char expected2[] = LIBDL_SO; -#ifdef LIBPTHREAD_SO - static const char expected3[] = LIBPTHREAD_SO; -#endif - static const char expected4[] = LD_SO; - - for (Lmid_t ns = 0; ns < GL(dl_nns); ++ns) - for (struct link_map *l = GL(dl_ns)[ns]._ns_loaded; l != NULL; - l = l->l_next) - if (caller >= (const void *) l->l_map_start - && caller < (const void *) l->l_text_end) - { - /* The address falls into this DSO's address range. Check the - name. */ - if ((mask & allow_libc) && strcmp (expected1, l->l_name) == 0) - return 0; - if ((mask & allow_libdl) && strcmp (expected2, l->l_name) == 0) - return 0; -#ifdef LIBPTHREAD_SO - if ((mask & allow_libpthread) && strcmp (expected3, l->l_name) == 0) - return 0; -#endif - if ((mask & allow_ldso) && strcmp (expected4, l->l_name) == 0) - return 0; - - struct libname_list *runp = l->l_libname; - - while (runp != NULL) - { - if ((mask & allow_libc) && strcmp (expected1, runp->name) == 0) - return 0; - if ((mask & allow_libdl) && strcmp (expected2, runp->name) == 0) - return 0; -#ifdef LIBPTHREAD_SO - if ((mask & allow_libpthread) - && strcmp (expected3, runp->name) == 0) - return 0; -#endif - if ((mask & allow_ldso) && strcmp (expected4, runp->name) == 0) - return 0; - - runp = runp->next; - } - - break; - } - - /* Maybe the dynamic linker is not yet on the list. */ - if ((mask & allow_ldso) != 0 - && caller >= (const void *) GL(dl_rtld_map).l_map_start - && caller < (const void *) GL(dl_rtld_map).l_text_end) - return 0; - - /* No valid caller. */ - return 1; -} diff --git a/elf/dl-close.c b/elf/dl-close.c deleted file mode 100644 index 2b46b7cf8b..0000000000 --- a/elf/dl-close.c +++ /dev/null @@ -1,843 +0,0 @@ -/* Close a shared object opened by `_dl_open'. - Copyright (C) 1996-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -#include <assert.h> -#include <dlfcn.h> -#include <errno.h> -#include <libintl.h> -#include <stddef.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <libc-lock.h> -#include <ldsodefs.h> -#include <sys/types.h> -#include <sys/mman.h> -#include <sysdep-cancel.h> -#include <tls.h> -#include <stap-probe.h> - -#include <dl-unmap-segments.h> - - -/* Type of the constructor functions. */ -typedef void (*fini_t) (void); - - -/* Special l_idx value used to indicate which objects remain loaded. */ -#define IDX_STILL_USED -1 - - -/* Returns true we an non-empty was found. */ -static bool -remove_slotinfo (size_t idx, struct dtv_slotinfo_list *listp, size_t disp, - bool should_be_there) -{ - if (idx - disp >= listp->len) - { - if (listp->next == NULL) - { - /* The index is not actually valid in the slotinfo list, - because this object was closed before it was fully set - up due to some error. */ - assert (! should_be_there); - } - else - { - if (remove_slotinfo (idx, listp->next, disp + listp->len, - should_be_there)) - return true; - - /* No non-empty entry. Search from the end of this element's - slotinfo array. */ - idx = disp + listp->len; - } - } - else - { - struct link_map *old_map = listp->slotinfo[idx - disp].map; - - /* The entry might still be in its unused state if we are closing an - object that wasn't fully set up. */ - if (__glibc_likely (old_map != NULL)) - { - assert (old_map->l_tls_modid == idx); - - /* Mark the entry as unused. */ - listp->slotinfo[idx - disp].gen = GL(dl_tls_generation) + 1; - listp->slotinfo[idx - disp].map = NULL; - } - - /* If this is not the last currently used entry no need to look - further. */ - if (idx != GL(dl_tls_max_dtv_idx)) - return true; - } - - while (idx - disp > (disp == 0 ? 1 + GL(dl_tls_static_nelem) : 0)) - { - --idx; - - if (listp->slotinfo[idx - disp].map != NULL) - { - /* Found a new last used index. */ - GL(dl_tls_max_dtv_idx) = idx; - return true; - } - } - - /* No non-entry in this list element. */ - return false; -} - - -void -_dl_close_worker (struct link_map *map, bool force) -{ - /* One less direct use. */ - --map->l_direct_opencount; - - /* If _dl_close is called recursively (some destructor call dlclose), - just record that the parent _dl_close will need to do garbage collection - again and return. */ - static enum { not_pending, pending, rerun } dl_close_state; - - if (map->l_direct_opencount > 0 || map->l_type != lt_loaded - || dl_close_state != not_pending) - { - if (map->l_direct_opencount == 0 && map->l_type == lt_loaded) - dl_close_state = rerun; - - /* There are still references to this object. Do nothing more. */ - 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); - - return; - } - - Lmid_t nsid = map->l_ns; - struct link_namespaces *ns = &GL(dl_ns)[nsid]; - - retry: - dl_close_state = pending; - - bool any_tls = false; - const unsigned int nloaded = ns->_ns_nloaded; - char used[nloaded]; - char done[nloaded]; - struct link_map *maps[nloaded]; - - /* Clear DF_1_NODELETE to force object deletion. We don't need to touch - l_tls_dtor_count because forced object deletion only happens when an - error occurs during object load. Destructor registration for TLS - non-POD objects should not have happened till then for this - object. */ - if (force) - map->l_flags_1 &= ~DF_1_NODELETE; - - /* Run over the list and assign indexes to the link maps and enter - them into the MAPS array. */ - int idx = 0; - for (struct link_map *l = ns->_ns_loaded; l != NULL; l = l->l_next) - { - l->l_idx = idx; - maps[idx] = l; - ++idx; - - } - assert (idx == nloaded); - - /* Prepare the bitmaps. */ - memset (used, '\0', sizeof (used)); - memset (done, '\0', sizeof (done)); - - /* Keep track of the lowest index link map we have covered already. */ - int done_index = -1; - while (++done_index < nloaded) - { - struct link_map *l = maps[done_index]; - - if (done[done_index]) - /* Already handled. */ - continue; - - /* Check whether this object is still used. */ - 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; - - /* We need this object and we handle it now. */ - done[done_index] = 1; - used[done_index] = 1; - /* Signal the object is still needed. */ - l->l_idx = IDX_STILL_USED; - - /* Mark all dependencies as used. */ - if (l->l_initfini != NULL) - { - /* We are always the zeroth entry, and since we don't include - ourselves in the dependency analysis start at 1. */ - struct link_map **lp = &l->l_initfini[1]; - while (*lp != NULL) - { - if ((*lp)->l_idx != IDX_STILL_USED) - { - assert ((*lp)->l_idx >= 0 && (*lp)->l_idx < nloaded); - - if (!used[(*lp)->l_idx]) - { - used[(*lp)->l_idx] = 1; - /* If we marked a new object as used, and we've - already processed it, then we need to go back - and process again from that point forward to - ensure we keep all of its dependencies also. */ - if ((*lp)->l_idx - 1 < done_index) - done_index = (*lp)->l_idx - 1; - } - } - - ++lp; - } - } - /* And the same for relocation dependencies. */ - if (l->l_reldeps != NULL) - for (unsigned int j = 0; j < l->l_reldeps->act; ++j) - { - struct link_map *jmap = l->l_reldeps->list[j]; - - if (jmap->l_idx != IDX_STILL_USED) - { - assert (jmap->l_idx >= 0 && jmap->l_idx < nloaded); - - if (!used[jmap->l_idx]) - { - used[jmap->l_idx] = 1; - if (jmap->l_idx - 1 < done_index) - done_index = jmap->l_idx - 1; - } - } - } - } - - /* Sort the entries. */ - _dl_sort_fini (maps, nloaded, used, nsid); - - /* Call all termination functions at once. */ -#ifdef SHARED - bool do_audit = GLRO(dl_naudit) > 0 && !ns->_ns_loaded->l_auditing; -#endif - bool unload_any = false; - bool scope_mem_left = false; - unsigned int unload_global = 0; - unsigned int first_loaded = ~0; - for (unsigned int i = 0; i < nloaded; ++i) - { - struct link_map *imap = maps[i]; - - /* All elements must be in the same namespace. */ - assert (imap->l_ns == nsid); - - if (!used[i]) - { - assert (imap->l_type == lt_loaded - && (imap->l_flags_1 & DF_1_NODELETE) == 0); - - /* Call its termination function. Do not do it for - half-cooked objects. */ - if (imap->l_init_called) - { - /* When debugging print a message first. */ - if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_IMPCALLS, - 0)) - _dl_debug_printf ("\ncalling fini: %s [%lu]\n\n", - imap->l_name, nsid); - - if (imap->l_info[DT_FINI_ARRAY] != NULL) - { - ElfW(Addr) *array = - (ElfW(Addr) *) (imap->l_addr - + imap->l_info[DT_FINI_ARRAY]->d_un.d_ptr); - unsigned int sz = (imap->l_info[DT_FINI_ARRAYSZ]->d_un.d_val - / sizeof (ElfW(Addr))); - - while (sz-- > 0) - ((fini_t) array[sz]) (); - } - - /* Next try the old-style destructor. */ - if (imap->l_info[DT_FINI] != NULL) - DL_CALL_DT_FINI (imap, ((void *) imap->l_addr - + imap->l_info[DT_FINI]->d_un.d_ptr)); - } - -#ifdef SHARED - /* Auditing checkpoint: we remove an object. */ - if (__glibc_unlikely (do_audit)) - { - struct audit_ifaces *afct = GLRO(dl_audit); - for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) - { - if (afct->objclose != NULL) - /* Return value is ignored. */ - (void) afct->objclose (&imap->l_audit[cnt].cookie); - - afct = afct->next; - } - } -#endif - - /* This object must not be used anymore. */ - imap->l_removed = 1; - - /* We indeed have an object to remove. */ - unload_any = true; - - if (imap->l_global) - ++unload_global; - - /* Remember where the first dynamically loaded object is. */ - if (i < first_loaded) - first_loaded = i; - } - /* Else used[i]. */ - else if (imap->l_type == lt_loaded) - { - struct r_scope_elem *new_list = NULL; - - if (imap->l_searchlist.r_list == NULL && imap->l_initfini != NULL) - { - /* The object is still used. But one of the objects we are - unloading right now is responsible for loading it. If - the current object does not have it's own scope yet we - have to create one. This has to be done before running - the finalizers. - - To do this count the number of dependencies. */ - unsigned int cnt; - for (cnt = 1; imap->l_initfini[cnt] != NULL; ++cnt) - ; - - /* We simply reuse the l_initfini list. */ - imap->l_searchlist.r_list = &imap->l_initfini[cnt + 1]; - imap->l_searchlist.r_nlist = cnt; - - new_list = &imap->l_searchlist; - } - - /* Count the number of scopes which remain after the unload. - When we add the local search list count it. Always add - one for the terminating NULL pointer. */ - size_t remain = (new_list != NULL) + 1; - bool removed_any = false; - for (size_t cnt = 0; imap->l_scope[cnt] != NULL; ++cnt) - /* This relies on l_scope[] entries being always set either - to its own l_symbolic_searchlist address, or some map's - l_searchlist address. */ - if (imap->l_scope[cnt] != &imap->l_symbolic_searchlist) - { - struct link_map *tmap = (struct link_map *) - ((char *) imap->l_scope[cnt] - - offsetof (struct link_map, l_searchlist)); - assert (tmap->l_ns == nsid); - if (tmap->l_idx == IDX_STILL_USED) - ++remain; - else - removed_any = true; - } - else - ++remain; - - if (removed_any) - { - /* Always allocate a new array for the scope. This is - necessary since we must be able to determine the last - user of the current array. If possible use the link map's - memory. */ - size_t new_size; - struct r_scope_elem **newp; - -#define SCOPE_ELEMS(imap) \ - (sizeof (imap->l_scope_mem) / sizeof (imap->l_scope_mem[0])) - - if (imap->l_scope != imap->l_scope_mem - && remain < SCOPE_ELEMS (imap)) - { - new_size = SCOPE_ELEMS (imap); - newp = imap->l_scope_mem; - } - else - { - new_size = imap->l_scope_max; - newp = (struct r_scope_elem **) - malloc (new_size * sizeof (struct r_scope_elem *)); - if (newp == NULL) - _dl_signal_error (ENOMEM, "dlclose", NULL, - N_("cannot create scope list")); - } - - /* Copy over the remaining scope elements. */ - remain = 0; - for (size_t cnt = 0; imap->l_scope[cnt] != NULL; ++cnt) - { - if (imap->l_scope[cnt] != &imap->l_symbolic_searchlist) - { - struct link_map *tmap = (struct link_map *) - ((char *) imap->l_scope[cnt] - - offsetof (struct link_map, l_searchlist)); - if (tmap->l_idx != IDX_STILL_USED) - { - /* Remove the scope. Or replace with own map's - scope. */ - if (new_list != NULL) - { - newp[remain++] = new_list; - new_list = NULL; - } - continue; - } - } - - newp[remain++] = imap->l_scope[cnt]; - } - newp[remain] = NULL; - - struct r_scope_elem **old = imap->l_scope; - - imap->l_scope = newp; - - /* No user anymore, we can free it now. */ - if (old != imap->l_scope_mem) - { - if (_dl_scope_free (old)) - /* If _dl_scope_free used THREAD_GSCOPE_WAIT (), - no need to repeat it. */ - scope_mem_left = false; - } - else - scope_mem_left = true; - - imap->l_scope_max = new_size; - } - else if (new_list != NULL) - { - /* We didn't change the scope array, so reset the search - list. */ - imap->l_searchlist.r_list = NULL; - imap->l_searchlist.r_nlist = 0; - } - - /* The loader is gone, so mark the object as not having one. - Note: l_idx != IDX_STILL_USED -> object will be removed. */ - if (imap->l_loader != NULL - && imap->l_loader->l_idx != IDX_STILL_USED) - imap->l_loader = NULL; - - /* Remember where the first dynamically loaded object is. */ - if (i < first_loaded) - first_loaded = i; - } - } - - /* If there are no objects to unload, do nothing further. */ - if (!unload_any) - goto out; - -#ifdef SHARED - /* Auditing checkpoint: we will start deleting objects. */ - if (__glibc_unlikely (do_audit)) - { - struct link_map *head = ns->_ns_loaded; - struct audit_ifaces *afct = GLRO(dl_audit); - /* Do not call the functions for any auditing object. */ - if (head->l_auditing == 0) - { - for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) - { - if (afct->activity != NULL) - afct->activity (&head->l_audit[cnt].cookie, LA_ACT_DELETE); - - afct = afct->next; - } - } - } -#endif - - /* Notify the debugger we are about to remove some loaded objects. */ - struct r_debug *r = _dl_debug_initialize (0, nsid); - r->r_state = RT_DELETE; - _dl_debug_state (); - LIBC_PROBE (unmap_start, 2, nsid, r); - - if (unload_global) - { - /* Some objects are in the global scope list. Remove them. */ - struct r_scope_elem *ns_msl = ns->_ns_main_searchlist; - unsigned int i; - unsigned int j = 0; - unsigned int cnt = ns_msl->r_nlist; - - while (cnt > 0 && ns_msl->r_list[cnt - 1]->l_removed) - --cnt; - - if (cnt + unload_global == ns_msl->r_nlist) - /* Speed up removing most recently added objects. */ - j = cnt; - else - for (i = 0; i < cnt; i++) - if (ns_msl->r_list[i]->l_removed == 0) - { - if (i != j) - ns_msl->r_list[j] = ns_msl->r_list[i]; - j++; - } - ns_msl->r_nlist = j; - } - - if (!RTLD_SINGLE_THREAD_P - && (unload_global - || scope_mem_left - || (GL(dl_scope_free_list) != NULL - && GL(dl_scope_free_list)->count))) - { - THREAD_GSCOPE_WAIT (); - - /* Now we can free any queued old scopes. */ - struct dl_scope_free_list *fsl = GL(dl_scope_free_list); - if (fsl != NULL) - while (fsl->count > 0) - free (fsl->list[--fsl->count]); - } - - size_t tls_free_start; - size_t tls_free_end; - tls_free_start = tls_free_end = NO_TLS_OFFSET; - - /* We modify the list of loaded objects. */ - __rtld_lock_lock_recursive (GL(dl_load_write_lock)); - - /* Check each element of the search list to see if all references to - it are gone. */ - for (unsigned int i = first_loaded; i < nloaded; ++i) - { - struct link_map *imap = maps[i]; - if (!used[i]) - { - assert (imap->l_type == lt_loaded); - - /* That was the last reference, and this was a dlopen-loaded - object. We can unmap it. */ - - /* Remove the object from the dtv slotinfo array if it uses TLS. */ - if (__glibc_unlikely (imap->l_tls_blocksize > 0)) - { - any_tls = true; - - if (GL(dl_tls_dtv_slotinfo_list) != NULL - && ! remove_slotinfo (imap->l_tls_modid, - GL(dl_tls_dtv_slotinfo_list), 0, - imap->l_init_called)) - /* All dynamically loaded modules with TLS are unloaded. */ - GL(dl_tls_max_dtv_idx) = GL(dl_tls_static_nelem); - - if (imap->l_tls_offset != NO_TLS_OFFSET - && imap->l_tls_offset != FORCED_DYNAMIC_TLS_OFFSET) - { - /* Collect a contiguous chunk built from the objects in - this search list, going in either direction. When the - whole chunk is at the end of the used area then we can - reclaim it. */ -#if TLS_TCB_AT_TP - if (tls_free_start == NO_TLS_OFFSET - || (size_t) imap->l_tls_offset == tls_free_start) - { - /* Extend the contiguous chunk being reclaimed. */ - tls_free_start - = imap->l_tls_offset - imap->l_tls_blocksize; - - if (tls_free_end == NO_TLS_OFFSET) - tls_free_end = imap->l_tls_offset; - } - else if (imap->l_tls_offset - imap->l_tls_blocksize - == tls_free_end) - /* Extend the chunk backwards. */ - tls_free_end = imap->l_tls_offset; - else - { - /* This isn't contiguous with the last chunk freed. - One of them will be leaked unless we can free - one block right away. */ - if (tls_free_end == GL(dl_tls_static_used)) - { - GL(dl_tls_static_used) = tls_free_start; - tls_free_end = imap->l_tls_offset; - tls_free_start - = tls_free_end - imap->l_tls_blocksize; - } - else if ((size_t) imap->l_tls_offset - == GL(dl_tls_static_used)) - GL(dl_tls_static_used) - = imap->l_tls_offset - imap->l_tls_blocksize; - else if (tls_free_end < (size_t) imap->l_tls_offset) - { - /* We pick the later block. It has a chance to - be freed. */ - tls_free_end = imap->l_tls_offset; - tls_free_start - = tls_free_end - imap->l_tls_blocksize; - } - } -#elif TLS_DTV_AT_TP - if (tls_free_start == NO_TLS_OFFSET) - { - tls_free_start = imap->l_tls_firstbyte_offset; - tls_free_end = (imap->l_tls_offset - + imap->l_tls_blocksize); - } - else if (imap->l_tls_firstbyte_offset == tls_free_end) - /* Extend the contiguous chunk being reclaimed. */ - tls_free_end = imap->l_tls_offset + imap->l_tls_blocksize; - else if (imap->l_tls_offset + imap->l_tls_blocksize - == tls_free_start) - /* Extend the chunk backwards. */ - tls_free_start = imap->l_tls_firstbyte_offset; - /* This isn't contiguous with the last chunk freed. - One of them will be leaked unless we can free - one block right away. */ - else if (imap->l_tls_offset + imap->l_tls_blocksize - == GL(dl_tls_static_used)) - GL(dl_tls_static_used) = imap->l_tls_firstbyte_offset; - else if (tls_free_end == GL(dl_tls_static_used)) - { - GL(dl_tls_static_used) = tls_free_start; - tls_free_start = imap->l_tls_firstbyte_offset; - tls_free_end = imap->l_tls_offset + imap->l_tls_blocksize; - } - else if (tls_free_end < imap->l_tls_firstbyte_offset) - { - /* We pick the later block. It has a chance to - be freed. */ - tls_free_start = imap->l_tls_firstbyte_offset; - tls_free_end = imap->l_tls_offset + imap->l_tls_blocksize; - } -#else -# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined" -#endif - } - } - - /* 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 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; - - /* Update the pointer to the head of the list - 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) - imap->l_next->l_prev = imap->l_prev; - - free (imap->l_versions); - if (imap->l_origin != (char *) -1) - free ((char *) imap->l_origin); - - free (imap->l_reldeps); - - /* Print debugging message. */ - 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); - - /* This name always is allocated. */ - free (imap->l_name); - /* Remove the list with all the names of the shared object. */ - - struct libname_list *lnp = imap->l_libname; - do - { - struct libname_list *this = lnp; - lnp = lnp->next; - if (!this->dont_free) - free (this); - } - while (lnp != NULL); - - /* Remove the searchlists. */ - free (imap->l_initfini); - - /* Remove the scope array if we allocated it. */ - if (imap->l_scope != imap->l_scope_mem) - free (imap->l_scope); - - if (imap->l_phdr_allocated) - free ((void *) imap->l_phdr); - - if (imap->l_rpath_dirs.dirs != (void *) -1) - free (imap->l_rpath_dirs.dirs); - if (imap->l_runpath_dirs.dirs != (void *) -1) - free (imap->l_runpath_dirs.dirs); - - free (imap); - } - } - - __rtld_lock_unlock_recursive (GL(dl_load_write_lock)); - - /* If we removed any object which uses TLS bump the generation counter. */ - if (any_tls) - { - 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)) - GL(dl_tls_static_used) = tls_free_start; - } - -#ifdef SHARED - /* Auditing checkpoint: we have deleted all objects. */ - if (__glibc_unlikely (do_audit)) - { - struct link_map *head = ns->_ns_loaded; - /* Do not call the functions for any auditing object. */ - if (head->l_auditing == 0) - { - struct audit_ifaces *afct = GLRO(dl_audit); - for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) - { - if (afct->activity != NULL) - afct->activity (&head->l_audit[cnt].cookie, LA_ACT_CONSISTENT); - - afct = afct->next; - } - } - } -#endif - - if (__builtin_expect (ns->_ns_loaded == NULL, 0) - && nsid == GL(dl_nns) - 1) - do - --GL(dl_nns); - while (GL(dl_ns)[GL(dl_nns) - 1]._ns_loaded == NULL); - - /* Notify the debugger those objects are finalized and gone. */ - r->r_state = RT_CONSISTENT; - _dl_debug_state (); - LIBC_PROBE (unmap_complete, 2, nsid, r); - - /* Recheck if we need to retry, release the lock. */ - out: - if (dl_close_state == rerun) - goto retry; - - dl_close_state = not_pending; -} - - -void -_dl_close (void *_map) -{ - struct link_map *map = _map; - - /* We must take the lock to examine the contents of map and avoid - concurrent dlopens. */ - __rtld_lock_lock_recursive (GL(dl_load_lock)); - - /* At this point we are guaranteed nobody else is touching the list of - loaded maps, but a concurrent dlclose might have freed our map - before we took the lock. There is no way to detect this (see below) - so we proceed assuming this isn't the case. First see whether we - can remove the object at all. */ - if (__glibc_unlikely (map->l_flags_1 & DF_1_NODELETE)) - { - /* Nope. Do nothing. */ - __rtld_lock_unlock_recursive (GL(dl_load_lock)); - return; - } - - /* At present this is an unreliable check except in the case where the - caller has recursively called dlclose and we are sure the link map - has not been freed. In a non-recursive dlclose the map itself - might have been freed and this access is potentially a data race - with whatever other use this memory might have now, or worse we - might silently corrupt memory if it looks enough like a link map. - POSIX has language in dlclose that appears to guarantee that this - should be a detectable case and given that dlclose should be threadsafe - we need this to be a reliable detection. - This is bug 20990. */ - if (__builtin_expect (map->l_direct_opencount, 1) == 0) - { - __rtld_lock_unlock_recursive (GL(dl_load_lock)); - _dl_signal_error (0, map->l_name, NULL, N_("shared object not open")); - } - - _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 deleted file mode 100644 index 3cbd07435e..0000000000 --- a/elf/dl-conflict.c +++ /dev/null @@ -1,74 +0,0 @@ -/* Resolve conflicts against already prelinked libraries. - Copyright (C) 2001-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Jakub Jelinek <jakub@redhat.com>, 2001. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public License as - published by the Free Software Foundation; either version 2.1 of the - License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; see the file COPYING.LIB. If - not, see <http://www.gnu.org/licenses/>. */ - -#include <errno.h> -#include <libintl.h> -#include <stdlib.h> -#include <unistd.h> -#include <ldsodefs.h> -#include <sys/mman.h> -#include <sys/param.h> -#include <sys/types.h> -#include "dynamic-link.h" - -void -_dl_resolve_conflicts (struct link_map *l, ElfW(Rela) *conflict, - ElfW(Rela) *conflictend) -{ -#if ! ELF_MACHINE_NO_RELA - if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_RELOC)) - _dl_debug_printf ("\nconflict processing: %s\n", DSO_FILENAME (l->l_name)); - - { - /* Do the conflict relocation of the object and library GOT and other - data. */ - - /* This macro is used as a callback from the ELF_DYNAMIC_RELOCATE code. */ -#define RESOLVE_MAP(ref, version, flags) (*ref = NULL, NULL) -#define RESOLVE(ref, version, flags) (*ref = NULL, 0) -#define RESOLVE_CONFLICT_FIND_MAP(map, r_offset) \ - do { \ - while ((resolve_conflict_map->l_map_end < (ElfW(Addr)) (r_offset)) \ - || (resolve_conflict_map->l_map_start > (ElfW(Addr)) (r_offset))) \ - resolve_conflict_map = resolve_conflict_map->l_next; \ - \ - (map) = resolve_conflict_map; \ - } while (0) - - /* Prelinking makes no sense for anything but the main namespace. */ - assert (l->l_ns == LM_ID_BASE); - struct link_map *resolve_conflict_map __attribute__ ((__unused__)) - = GL(dl_ns)[LM_ID_BASE]._ns_loaded; - -#include "dynamic-link.h" - - /* Override these, defined in dynamic-link.h. */ -#undef CHECK_STATIC_TLS -#define CHECK_STATIC_TLS(ref_map, sym_map) ((void) 0) -#undef TRY_STATIC_TLS -#define TRY_STATIC_TLS(ref_map, sym_map) (0) - - GL(dl_num_cache_relocations) += conflictend - conflict; - - for (; conflict < conflictend; ++conflict) - elf_machine_rela (l, conflict, NULL, NULL, (void *) conflict->r_offset, - 0); - } -#endif -} diff --git a/elf/dl-debug.c b/elf/dl-debug.c deleted file mode 100644 index f3957044f6..0000000000 --- a/elf/dl-debug.c +++ /dev/null @@ -1,76 +0,0 @@ -/* Communicate dynamic linker state to the debugger at runtime. - Copyright (C) 1996-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -#include <ldsodefs.h> - - -/* These are the members in the public `struct link_map' type. - Sanity check that the internal type and the public type match. */ -#define VERIFY_MEMBER(name) \ - (offsetof (struct link_map_public, name) == offsetof (struct link_map, name)) -extern const int verify_link_map_members[(VERIFY_MEMBER (l_addr) - && VERIFY_MEMBER (l_name) - && VERIFY_MEMBER (l_ld) - && VERIFY_MEMBER (l_next) - && VERIFY_MEMBER (l_prev)) - ? 1 : -1]; - -/* This structure communicates dl state to the debugger. The debugger - normally finds it via the DT_DEBUG entry in the dynamic section, but in - a statically-linked program there is no dynamic section for the debugger - to examine and it looks for this particular symbol name. */ -struct r_debug _r_debug; - - -/* Initialize _r_debug if it has not already been done. The argument is - the run-time load address of the dynamic linker, to be put in - _r_debug.r_ldbase. Returns the address of _r_debug. */ - -struct r_debug * -internal_function -_dl_debug_initialize (ElfW(Addr) ldbase, Lmid_t ns) -{ - struct r_debug *r; - - if (ns == LM_ID_BASE) - r = &_r_debug; - else - r = &GL(dl_ns)[ns]._ns_debug; - - if (r->r_map == NULL || ldbase != 0) - { - /* Tell the debugger where to find the map of loaded objects. */ - r->r_version = 1 /* R_DEBUG_VERSION XXX */; - r->r_ldbase = ldbase ?: _r_debug.r_ldbase; - r->r_map = (void *) GL(dl_ns)[ns]._ns_loaded; - r->r_brk = (ElfW(Addr)) &_dl_debug_state; - } - - return r; -} - - -/* This function exists solely to have a breakpoint set on it by the - debugger. The debugger is supposed to find this function's address by - examining the r_brk member of struct r_debug, but GDB 4.15 in fact looks - for this particular symbol name in the PT_INTERP file. */ -void -_dl_debug_state (void) -{ -} -rtld_hidden_def (_dl_debug_state) diff --git a/elf/dl-deps.c b/elf/dl-deps.c deleted file mode 100644 index 1b8bac6593..0000000000 --- a/elf/dl-deps.c +++ /dev/null @@ -1,688 +0,0 @@ -/* Load the dependencies of a mapped object. - Copyright (C) 1996-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -#include <atomic.h> -#include <assert.h> -#include <dlfcn.h> -#include <errno.h> -#include <libintl.h> -#include <stddef.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <sys/param.h> -#include <ldsodefs.h> - -#include <dl-dst.h> - -/* Whether an shared object references one or more auxiliary objects - is signaled by the AUXTAG entry in l_info. */ -#define AUXTAG (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGNUM \ - + DT_EXTRATAGIDX (DT_AUXILIARY)) -/* Whether an shared object references one or more auxiliary objects - is signaled by the AUXTAG entry in l_info. */ -#define FILTERTAG (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGNUM \ - + DT_EXTRATAGIDX (DT_FILTER)) - - -/* When loading auxiliary objects we must ignore errors. It's ok if - an object is missing. */ -struct openaux_args - { - /* The arguments to openaux. */ - struct link_map *map; - int trace_mode; - int open_mode; - const char *strtab; - const char *name; - - /* The return value of openaux. */ - struct link_map *aux; - }; - -static void -openaux (void *a) -{ - struct openaux_args *args = (struct openaux_args *) a; - - args->aux = _dl_map_object (args->map, args->name, - (args->map->l_type == lt_executable - ? lt_library : args->map->l_type), - args->trace_mode, args->open_mode, - args->map->l_ns); -} - -static ptrdiff_t -internal_function -_dl_build_local_scope (struct link_map **list, struct link_map *map) -{ - struct link_map **p = list; - struct link_map **q; - - *p++ = map; - map->l_reserved = 1; - if (map->l_initfini) - for (q = map->l_initfini + 1; *q; ++q) - if (! (*q)->l_reserved) - p += _dl_build_local_scope (p, *q); - return p - list; -} - - -/* We use a very special kind of list to track the path - through the list of loaded shared objects. We have to - produce a flat list with unique members of all involved objects. -*/ -struct list - { - int done; /* Nonzero if this map was processed. */ - struct link_map *map; /* The data. */ - struct list *next; /* Elements for normal list. */ - }; - - -/* Macro to expand DST. It is an macro since we use `alloca'. */ -#define expand_dst(l, str, fatal) \ - ({ \ - const char *__str = (str); \ - const char *__result = __str; \ - size_t __dst_cnt = DL_DST_COUNT (__str, 0); \ - \ - if (__dst_cnt != 0) \ - { \ - char *__newp; \ - \ - /* DST must not appear in SUID/SGID programs. */ \ - if (__libc_enable_secure) \ - _dl_signal_error (0, __str, NULL, N_("\ -DST not allowed in SUID/SGID programs")); \ - \ - __newp = (char *) alloca (DL_DST_REQUIRED (l, __str, strlen (__str), \ - __dst_cnt)); \ - \ - __result = _dl_dst_substitute (l, __str, __newp, 0); \ - \ - if (*__result == '\0') \ - { \ - /* The replacement for the DST is not known. We can't \ - processed. */ \ - if (fatal) \ - _dl_signal_error (0, __str, NULL, N_("\ -empty dynamic string token substitution")); \ - else \ - { \ - /* This is for DT_AUXILIARY. */ \ - 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); \ - continue; \ - } \ - } \ - } \ - \ - __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 -_dl_map_object_deps (struct link_map *map, - struct link_map **preloads, unsigned int npreloads, - int trace_mode, int open_mode) -{ - struct list *known = __alloca (sizeof *known * (1 + npreloads + 1)); - struct list *runp, *tail; - unsigned int nlist, i; - /* Object name. */ - const char *name; - int errno_saved; - int errno_reason; - const char *errstring; - const char *objname; - - /* No loaded object so far. */ - nlist = 0; - - /* First load MAP itself. */ - preload (known, &nlist, map); - - /* Add the preloaded items after MAP but before any of its dependencies. */ - for (i = 0; i < npreloads; ++i) - preload (known, &nlist, preloads[i]); - - /* Terminate the lists. */ - known[nlist - 1].next = NULL; - - /* Pointer to last unique object. */ - tail = &known[nlist - 1]; - - /* No alloca'd space yet. */ - struct link_map **needed_space = NULL; - size_t needed_space_bytes = 0; - - /* Process each element of the search list, loading each of its - auxiliary objects and immediate dependencies. Auxiliary objects - will be added in the list before the object itself and - dependencies will be appended to the list as we step through it. - This produces a flat, ordered list that represents a - breadth-first search of the dependency tree. - - The whole process is complicated by the fact that we better - should use alloca for the temporary list elements. But using - alloca means we cannot use recursive function calls. */ - errno_saved = errno; - errno_reason = 0; - errstring = NULL; - errno = 0; - name = NULL; - for (runp = known; runp; ) - { - struct link_map *l = runp->map; - struct link_map **needed = NULL; - unsigned int nneeded = 0; - - /* Unless otherwise stated, this object is handled. */ - runp->done = 1; - - /* Allocate a temporary record to contain the references to the - dependencies of this object. */ - if (l->l_searchlist.r_list == NULL && l->l_initfini == NULL - && l != map && l->l_ldnum > 0) - { - size_t new_size = l->l_ldnum * sizeof (struct link_map *); - - if (new_size > needed_space_bytes) - needed_space - = extend_alloca (needed_space, needed_space_bytes, new_size); - - needed = needed_space; - } - - if (l->l_info[DT_NEEDED] || l->l_info[AUXTAG] || l->l_info[FILTERTAG]) - { - const char *strtab = (const void *) D_PTR (l, l_info[DT_STRTAB]); - struct openaux_args args; - struct list *orig; - const ElfW(Dyn) *d; - - args.strtab = strtab; - args.map = l; - args.trace_mode = trace_mode; - args.open_mode = open_mode; - orig = runp; - - for (d = l->l_ld; d->d_tag != DT_NULL; ++d) - if (__builtin_expect (d->d_tag, DT_NEEDED) == DT_NEEDED) - { - /* Map in the needed object. */ - struct link_map *dep; - - /* Recognize DSTs. */ - name = expand_dst (l, strtab + d->d_un.d_val, 0); - /* Store the tag in the argument structure. */ - args.name = name; - - bool malloced; - int err = _dl_catch_error (&objname, &errstring, &malloced, - openaux, &args); - if (__glibc_unlikely (errstring != NULL)) - { - char *new_errstring = strdupa (errstring); - objname = strdupa (objname); - if (malloced) - free ((char *) errstring); - errstring = new_errstring; - - if (err) - errno_reason = err; - else - errno_reason = -1; - goto out; - } - else - dep = args.aux; - - if (! dep->l_reserved) - { - /* Allocate new entry. */ - struct list *newp; - - newp = alloca (sizeof (struct list)); - - /* Append DEP to the list. */ - newp->map = dep; - newp->done = 0; - newp->next = NULL; - tail->next = newp; - tail = newp; - ++nlist; - /* Set the mark bit that says it's already in the list. */ - dep->l_reserved = 1; - } - - /* Remember this dependency. */ - if (needed != NULL) - needed[nneeded++] = dep; - } - else if (d->d_tag == DT_AUXILIARY || d->d_tag == DT_FILTER) - { - struct list *newp; - - /* Recognize DSTs. */ - name = expand_dst (l, strtab + d->d_un.d_val, - d->d_tag == DT_AUXILIARY); - /* Store the tag in the argument structure. */ - args.name = name; - - /* 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)) - { - if (d->d_tag == DT_AUXILIARY) - { - /* We are not interested in the error message. */ - assert (errstring != NULL); - if (malloced) - free ((char *) errstring); - - /* Simply ignore this error and continue the work. */ - continue; - } - else - { - - char *new_errstring = strdupa (errstring); - objname = strdupa (objname); - if (malloced) - free ((char *) errstring); - errstring = new_errstring; - - if (err) - errno_reason = err; - else - errno_reason = -1; - goto out; - } - } - - /* The auxiliary object is actually available. - Incorporate the map in all the lists. */ - - /* Allocate new entry. This always has to be done. */ - newp = alloca (sizeof (struct list)); - - /* We want to insert the new map before the current one, - but we have no back links. So we copy the contents of - the current entry over. Note that ORIG and NEWP now - have switched their meanings. */ - memcpy (newp, orig, sizeof (*newp)); - - /* Initialize new entry. */ - orig->done = 0; - orig->map = args.aux; - - /* Remember this dependency. */ - if (needed != NULL) - needed[nneeded++] = args.aux; - - /* We must handle two situations here: the map is new, - so we must add it in all three lists. If the map - is already known, we have two further possibilities: - - if the object is before the current map in the - search list, we do nothing. It is already found - early - - if the object is after the current one, we must - move it just before the current map to make sure - the symbols are found early enough - */ - if (args.aux->l_reserved) - { - /* The object is already somewhere in the list. - Locate it first. */ - struct list *late; - - /* This object is already in the search list we - are building. Don't add a duplicate pointer. - Just added by _dl_map_object. */ - for (late = newp; late->next != NULL; late = late->next) - if (late->next->map == args.aux) - break; - - if (late->next != NULL) - { - /* The object is somewhere behind the current - position in the search path. We have to - move it to this earlier position. */ - orig->next = newp; - - /* Now remove the later entry from the list - and adjust the tail pointer. */ - if (tail == late->next) - tail = late; - late->next = late->next->next; - - /* We must move the object earlier in the chain. */ - if (args.aux->l_prev != NULL) - args.aux->l_prev->l_next = args.aux->l_next; - if (args.aux->l_next != NULL) - args.aux->l_next->l_prev = args.aux->l_prev; - - args.aux->l_prev = newp->map->l_prev; - newp->map->l_prev = args.aux; - if (args.aux->l_prev != NULL) - args.aux->l_prev->l_next = args.aux; - args.aux->l_next = newp->map; - } - else - { - /* The object must be somewhere earlier in the - list. Undo to the current list element what - we did above. */ - memcpy (orig, newp, sizeof (*newp)); - continue; - } - } - else - { - /* This is easy. We just add the symbol right here. */ - orig->next = newp; - ++nlist; - /* Set the mark bit that says it's already in the list. */ - args.aux->l_reserved = 1; - - /* The only problem is that in the double linked - list of all objects we don't have this new - object at the correct place. Correct this here. */ - if (args.aux->l_prev) - args.aux->l_prev->l_next = args.aux->l_next; - if (args.aux->l_next) - args.aux->l_next->l_prev = args.aux->l_prev; - - args.aux->l_prev = newp->map->l_prev; - newp->map->l_prev = args.aux; - if (args.aux->l_prev != NULL) - args.aux->l_prev->l_next = args.aux; - args.aux->l_next = newp->map; - } - - /* Move the tail pointer if necessary. */ - if (orig == tail) - tail = newp; - - /* Move on the insert point. */ - orig = newp; - } - } - - /* Terminate the list of dependencies and store the array address. */ - if (needed != NULL) - { - needed[nneeded++] = NULL; - - struct link_map **l_initfini = (struct link_map **) - malloc ((2 * nneeded + 1) * sizeof needed[0]); - if (l_initfini == NULL) - _dl_signal_error (ENOMEM, map->l_name, NULL, - N_("cannot allocate dependency list")); - l_initfini[0] = l; - memcpy (&l_initfini[1], needed, nneeded * sizeof needed[0]); - memcpy (&l_initfini[nneeded + 1], l_initfini, - nneeded * sizeof needed[0]); - atomic_write_barrier (); - l->l_initfini = l_initfini; - l->l_free_initfini = 1; - } - - /* If we have no auxiliary objects just go on to the next map. */ - if (runp->done) - do - runp = runp->next; - while (runp != NULL && runp->done); - } - - out: - if (errno == 0 && errno_saved != 0) - __set_errno (errno_saved); - - struct link_map **old_l_initfini = NULL; - if (map->l_initfini != NULL && map->l_type == lt_loaded) - { - /* This object was previously loaded as a dependency and we have - a separate l_initfini list. We don't need it anymore. */ - assert (map->l_searchlist.r_list == NULL); - old_l_initfini = map->l_initfini; - } - - /* Store the search list we built in the object. It will be used for - searches in the scope of this object. */ - struct link_map **l_initfini = - (struct link_map **) malloc ((2 * nlist + 1) - * sizeof (struct link_map *)); - if (l_initfini == NULL) - _dl_signal_error (ENOMEM, map->l_name, NULL, - N_("cannot allocate symbol search list")); - - - map->l_searchlist.r_list = &l_initfini[nlist + 1]; - map->l_searchlist.r_nlist = nlist; - - for (nlist = 0, runp = known; runp; runp = runp->next) - { - if (__builtin_expect (trace_mode, 0) && runp->map->l_faked) - /* This can happen when we trace the loading. */ - --map->l_searchlist.r_nlist; - else - map->l_searchlist.r_list[nlist++] = runp->map; - - /* Now clear all the mark bits we set in the objects on the search list - to avoid duplicates, so the next call starts fresh. */ - runp->map->l_reserved = 0; - } - - if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_PRELINK, 0) != 0 - && map == GL(dl_ns)[LM_ID_BASE]._ns_loaded) - { - /* If we are to compute conflicts, we have to build local scope - for each library, not just the ultimate loader. */ - for (i = 0; i < nlist; ++i) - { - struct link_map *l = map->l_searchlist.r_list[i]; - unsigned int j, cnt; - - /* The local scope has been already computed. */ - if (l == map - || (l->l_local_scope[0] - && l->l_local_scope[0]->r_nlist) != 0) - continue; - - if (l->l_info[AUXTAG] || l->l_info[FILTERTAG]) - { - /* As current DT_AUXILIARY/DT_FILTER implementation needs to be - rewritten, no need to bother with prelinking the old - implementation. */ - _dl_signal_error (EINVAL, l->l_name, NULL, N_("\ -Filters not supported with LD_TRACE_PRELINKING")); - } - - cnt = _dl_build_local_scope (l_initfini, l); - assert (cnt <= nlist); - for (j = 0; j < cnt; j++) - { - l_initfini[j]->l_reserved = 0; - if (j && __builtin_expect (l_initfini[j]->l_info[DT_SYMBOLIC] - != NULL, 0)) - l->l_symbolic_in_local_scope = true; - } - - l->l_local_scope[0] = - (struct r_scope_elem *) malloc (sizeof (struct r_scope_elem) - + (cnt - * sizeof (struct link_map *))); - if (l->l_local_scope[0] == NULL) - _dl_signal_error (ENOMEM, map->l_name, NULL, - N_("cannot allocate symbol search list")); - l->l_local_scope[0]->r_nlist = cnt; - l->l_local_scope[0]->r_list = - (struct link_map **) (l->l_local_scope[0] + 1); - memcpy (l->l_local_scope[0]->r_list, l_initfini, - cnt * sizeof (struct link_map *)); - } - } - - /* Maybe we can remove some relocation dependencies now. */ - assert (map->l_searchlist.r_list[0] == map); - struct link_map_reldeps *l_reldeps = NULL; - if (map->l_reldeps != NULL) - { - for (i = 1; i < nlist; ++i) - map->l_searchlist.r_list[i]->l_reserved = 1; - - struct link_map **list = &map->l_reldeps->list[0]; - for (i = 0; i < map->l_reldeps->act; ++i) - if (list[i]->l_reserved) - { - /* Need to allocate new array of relocation dependencies. */ - l_reldeps = malloc (sizeof (*l_reldeps) - + map->l_reldepsmax - * sizeof (struct link_map *)); - if (l_reldeps == NULL) - /* Bad luck, keep the reldeps duplicated between - map->l_reldeps->list and map->l_initfini lists. */ - ; - else - { - unsigned int j = i; - memcpy (&l_reldeps->list[0], &list[0], - i * sizeof (struct link_map *)); - for (i = i + 1; i < map->l_reldeps->act; ++i) - if (!list[i]->l_reserved) - l_reldeps->list[j++] = list[i]; - l_reldeps->act = j; - } - } - - for (i = 1; i < nlist; ++i) - map->l_searchlist.r_list[i]->l_reserved = 0; - } - - /* Sort the initializer list to take dependencies into account. The binary - itself will always be initialize last. */ - memcpy (l_initfini, map->l_searchlist.r_list, - nlist * sizeof (struct link_map *)); - if (__glibc_likely (nlist > 1)) - { - /* We can skip looking for the binary itself which is at the front - of the search list. */ - i = 1; - uint16_t seen[nlist]; - memset (seen, 0, nlist * sizeof (seen[0])); - while (1) - { - /* Keep track of which object we looked at this round. */ - ++seen[i]; - struct link_map *thisp = l_initfini[i]; - - /* Find the last object in the list for which the current one is - a dependency and move the current object behind the object - with the dependency. */ - unsigned int k = nlist - 1; - while (k > i) - { - struct link_map **runp = l_initfini[k]->l_initfini; - if (runp != NULL) - /* Look through the dependencies of the object. */ - while (*runp != NULL) - if (__glibc_unlikely (*runp++ == thisp)) - { - /* Move the current object to the back past the last - object with it as the dependency. */ - memmove (&l_initfini[i], &l_initfini[i + 1], - (k - i) * sizeof (l_initfini[0])); - l_initfini[k] = thisp; - - if (seen[i + 1] > nlist - i) - { - ++i; - goto next_clear; - } - - uint16_t this_seen = seen[i]; - memmove (&seen[i], &seen[i + 1], - (k - i) * sizeof (seen[0])); - seen[k] = this_seen; - - goto next; - } - - --k; - } - - if (++i == nlist) - break; - next_clear: - memset (&seen[i], 0, (nlist - i) * sizeof (seen[0])); - - next:; - } - } - - /* Terminate the list of dependencies. */ - l_initfini[nlist] = NULL; - atomic_write_barrier (); - map->l_initfini = l_initfini; - map->l_free_initfini = 1; - if (l_reldeps != NULL) - { - atomic_write_barrier (); - void *old_l_reldeps = map->l_reldeps; - map->l_reldeps = l_reldeps; - _dl_scope_free (old_l_reldeps); - } - if (old_l_initfini != NULL) - _dl_scope_free (old_l_initfini); - - if (errno_reason) - _dl_signal_error (errno_reason == -1 ? 0 : errno_reason, objname, - NULL, errstring); -} diff --git a/elf/dl-dst.h b/elf/dl-dst.h deleted file mode 100644 index a96513d4dc..0000000000 --- a/elf/dl-dst.h +++ /dev/null @@ -1,74 +0,0 @@ -/* Handling of dynamic sring tokens. - Copyright (C) 1999-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -#include "trusted-dirs.h" - -/* Determine the number of DST elements in the name. Only if IS_PATH is - nonzero paths are recognized (i.e., multiple, ':' separated filenames). */ -#define DL_DST_COUNT(name, is_path) \ - ({ \ - size_t __cnt = 0; \ - const char *__sf = strchr (name, '$'); \ - \ - if (__glibc_unlikely (__sf != NULL)) \ - __cnt = _dl_dst_count (__sf, is_path); \ - \ - __cnt; }) - - -#ifdef SHARED -# define IS_RTLD(l) (l) == &GL(dl_rtld_map) -#else -# define IS_RTLD(l) 0 -#endif -/* Guess from the number of DSTs the length of the result string. */ -#define DL_DST_REQUIRED(l, name, len, cnt) \ - ({ \ - size_t __len = (len); \ - size_t __cnt = (cnt); \ - \ - if (__cnt > 0) \ - { \ - size_t dst_len; \ - /* Now we make a guess how many extra characters on top of the \ - length of S we need to represent the result. We know that \ - we have CNT replacements. Each at most can use \ - MAX (MAX (strlen (ORIGIN), strlen (_dl_platform)), \ - strlen (DL_DST_LIB)) \ - minus 4 (which is the length of "$LIB"). \ - \ - First get the origin string if it is not available yet. \ - This can only happen for the map of the executable or, when \ - auditing, in ld.so. */ \ - if ((l)->l_origin == NULL) \ - { \ - assert ((l)->l_name[0] == '\0' || IS_RTLD (l)); \ - (l)->l_origin = _dl_get_origin (); \ - dst_len = ((l)->l_origin && (l)->l_origin != (char *) -1 \ - ? strlen ((l)->l_origin) : 0); \ - } \ - else \ - dst_len = (l)->l_origin == (char *) -1 \ - ? 0 : strlen ((l)->l_origin); \ - dst_len = MAX (MAX (dst_len, GLRO(dl_platformlen)), \ - strlen (DL_DST_LIB)); \ - if (dst_len > 4) \ - __len += __cnt * (dst_len - 4); \ - } \ - \ - __len; }) diff --git a/elf/dl-environ.c b/elf/dl-environ.c deleted file mode 100644 index cbffec8808..0000000000 --- a/elf/dl-environ.c +++ /dev/null @@ -1,85 +0,0 @@ -/* Environment handling for dynamic loader. - Copyright (C) 1995-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -#include <string.h> -#include <stdlib.h> -#include <unistd.h> -#include <ldsodefs.h> - -/* Walk through the environment of the process and return all entries - starting with `LD_'. */ -char * -internal_function -_dl_next_ld_env_entry (char ***position) -{ - char **current = *position; - char *result = NULL; - - while (*current != NULL) - { - if (__builtin_expect ((*current)[0] == 'L', 0) - && (*current)[1] == 'D' && (*current)[2] == '_') - { - result = &(*current)[3]; - - /* Save current position for next visit. */ - *position = ++current; - - break; - } - - ++current; - } - - return result; -} - - -/* In ld.so __environ is not exported. */ -extern char **__environ attribute_hidden; - -int -unsetenv (const char *name) -{ - char **ep; - - ep = __environ; - while (*ep != NULL) - { - size_t cnt = 0; - - while ((*ep)[cnt] == name[cnt] && name[cnt] != '\0') - ++cnt; - - if (name[cnt] == '\0' && (*ep)[cnt] == '=') - { - /* Found it. Remove this pointer by moving later ones to - the front. */ - char **dp = ep; - - do - dp[0] = dp[1]; - while (*dp++); - /* Continue the loop in case NAME appears again. */ - } - else - ++ep; - } - - return 0; -} diff --git a/elf/dl-error-minimal.c b/elf/dl-error-minimal.c deleted file mode 100644 index 384c9b0edc..0000000000 --- a/elf/dl-error-minimal.c +++ /dev/null @@ -1,23 +0,0 @@ -/* Error handling for runtime dynamic linker, minimal version. - Copyright (C) 1995-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -/* This version does lives in ld.so, does not use thread-local data - and supports _dl_signal_cerror and _dl_receive_error. */ - -#define DL_ERROR_BOOTSTRAP 1 -#include "dl-error-skeleton.c" diff --git a/elf/dl-error-skeleton.c b/elf/dl-error-skeleton.c deleted file mode 100644 index 8e5888d4bd..0000000000 --- a/elf/dl-error-skeleton.c +++ /dev/null @@ -1,230 +0,0 @@ -/* Template for error handling for runtime dynamic linker. - Copyright (C) 1995-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -/* The following macro needs to be defined before including this - skeleton file: - - DL_ERROR_BOOTSTRAP - - If 1, do not use TLS and implement _dl_signal_cerror and - _dl_receive_error. If 0, TLS is used, and the variants with - error callbacks are not provided. */ - - -#include <libintl.h> -#include <setjmp.h> -#include <stdbool.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <ldsodefs.h> -#include <stdio.h> - -/* This structure communicates state between _dl_catch_error and - _dl_signal_error. */ -struct catch - { - const char **objname; /* Object/File name. */ - const char **errstring; /* Error detail filled in here. */ - bool *malloced; /* Nonzero if the string is malloced - by the libc malloc. */ - volatile int *errcode; /* Return value of _dl_signal_error. */ - jmp_buf env; /* longjmp here on error. */ - }; - -/* Multiple threads at once can use the `_dl_catch_error' function. The - calls can come from `_dl_map_object_deps', `_dlerror_run', or from - any of the libc functionality which loads dynamic objects (NSS, iconv). - Therefore we have to be prepared to save the state in thread-local - memory. */ -#if !DL_ERROR_BOOTSTRAP -static __thread struct catch *catch_hook attribute_tls_model_ie; -#else -/* The version of this code in ld.so cannot use thread-local variables - and is used during bootstrap only. */ -static struct catch *catch_hook; -#endif - -/* This message we return as a last resort. We define the string in a - variable since we have to avoid freeing it and so have to enable - a pointer comparison. See below and in dlfcn/dlerror.c. */ -static const char _dl_out_of_memory[] = "out of memory"; - -#if DL_ERROR_BOOTSTRAP -/* This points to a function which is called when an continuable error is - received. Unlike the handling of `catch' this function may return. - The arguments will be the `errstring' and `objname'. - - Since this functionality is not used in normal programs (only in ld.so) - we do not care about multi-threaded programs here. We keep this as a - global variable. */ -static receiver_fct receiver; -#endif /* DL_ERROR_BOOTSTRAP */ - -void -internal_function -_dl_signal_error (int errcode, const char *objname, const char *occation, - const char *errstring) -{ - struct catch *lcatch = catch_hook; - - if (! errstring) - errstring = N_("DYNAMIC LINKER BUG!!!"); - - if (objname == NULL) - objname = ""; - if (lcatch != NULL) - { - /* We are inside _dl_catch_error. Return to it. We have to - duplicate the error string since it might be allocated on the - stack. The object name is always a string constant. */ - size_t len_objname = strlen (objname) + 1; - size_t len_errstring = strlen (errstring) + 1; - - char *errstring_copy = malloc (len_objname + len_errstring); - if (errstring_copy != NULL) - { - /* Make a copy of the object file name and the error string. */ - *lcatch->objname = memcpy (__mempcpy (errstring_copy, - errstring, len_errstring), - objname, len_objname); - *lcatch->errstring = errstring_copy; - - /* If the main executable is relocated it means the libc's malloc - is used. */ - bool malloced = true; -#ifdef SHARED - malloced = (GL(dl_ns)[LM_ID_BASE]._ns_loaded != NULL - && (GL(dl_ns)[LM_ID_BASE]._ns_loaded->l_relocated != 0)); -#endif - *lcatch->malloced = malloced; - } - else - { - /* This is better than nothing. */ - *lcatch->objname = ""; - *lcatch->errstring = _dl_out_of_memory; - *lcatch->malloced = false; - } - - *lcatch->errcode = errcode; - - /* We do not restore the signal mask because none was saved. */ - __longjmp (lcatch->env[0].__jmpbuf, 1); - } - else - { - /* Lossage while resolving the program's own symbols is always fatal. */ - char buffer[1024]; - _dl_fatal_printf ("%s: %s: %s%s%s%s%s\n", - RTLD_PROGNAME, - occation ?: N_("error while loading shared libraries"), - objname, *objname ? ": " : "", - errstring, errcode ? ": " : "", - (errcode - ? __strerror_r (errcode, buffer, sizeof buffer) - : "")); - } -} -libc_hidden_def (_dl_signal_error) - - -#if DL_ERROR_BOOTSTRAP -void -internal_function -_dl_signal_cerror (int errcode, const char *objname, const char *occation, - const char *errstring) -{ - if (__builtin_expect (GLRO(dl_debug_mask) - & ~(DL_DEBUG_STATISTICS|DL_DEBUG_PRELINK), 0)) - _dl_debug_printf ("%s: error: %s: %s (%s)\n", objname, occation, - errstring, receiver ? "continued" : "fatal"); - - if (receiver) - { - /* We are inside _dl_receive_error. Call the user supplied - handler and resume the work. The receiver will still be - installed. */ - (*receiver) (errcode, objname, errstring); - } - else - _dl_signal_error (errcode, objname, occation, errstring); -} -#endif /* DL_ERROR_BOOTSTRAP */ - - -int -internal_function -_dl_catch_error (const char **objname, const char **errstring, - bool *mallocedp, void (*operate) (void *), void *args) -{ - /* We need not handle `receiver' since setting a `catch' is handled - before it. */ - - /* Only this needs to be marked volatile, because it is the only local - variable that gets changed between the setjmp invocation and the - longjmp call. All others are just set here (before setjmp) and read - in _dl_signal_error (before longjmp). */ - volatile int errcode; - - struct catch c; - /* Don't use an initializer since we don't need to clear C.env. */ - c.objname = objname; - c.errstring = errstring; - c.malloced = mallocedp; - c.errcode = &errcode; - - struct catch *const old = catch_hook; - catch_hook = &c; - - /* Do not save the signal mask. */ - if (__builtin_expect (__sigsetjmp (c.env, 0), 0) == 0) - { - (*operate) (args); - catch_hook = old; - *objname = NULL; - *errstring = NULL; - *mallocedp = false; - return 0; - } - - /* We get here only if we longjmp'd out of OPERATE. _dl_signal_error has - already stored values into *OBJNAME, *ERRSTRING, and *MALLOCEDP. */ - catch_hook = old; - return errcode; -} -libc_hidden_def (_dl_catch_error) - -#if DL_ERROR_BOOTSTRAP -void -internal_function -_dl_receive_error (receiver_fct fct, void (*operate) (void *), void *args) -{ - struct catch *old_catch = catch_hook; - receiver_fct old_receiver = receiver; - - /* Set the new values. */ - catch_hook = NULL; - receiver = fct; - - (*operate) (args); - - catch_hook = old_catch; - receiver = old_receiver; -} -#endif /* DL_ERROR_BOOTSTRAP */ diff --git a/elf/dl-error.c b/elf/dl-error.c deleted file mode 100644 index bfcbd5358b..0000000000 --- a/elf/dl-error.c +++ /dev/null @@ -1,27 +0,0 @@ -/* Error handling for runtime dynamic linker, full version. - Copyright (C) 1995-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -/* This implementation lives in libc.so because it uses thread-local - data, which is not available in ld.so. It interposes the version - in dl-error-minimal.c after ld.so bootstrap. - - The signal/catch mechanism is used by the audit framework, which - means that even in ld.so, not all errors are fatal. */ - -#define DL_ERROR_BOOTSTRAP 0 -#include "dl-error-skeleton.c" diff --git a/elf/dl-execstack.c b/elf/dl-execstack.c deleted file mode 100644 index 875338bea5..0000000000 --- a/elf/dl-execstack.c +++ /dev/null @@ -1,31 +0,0 @@ -/* Stack executability handling for GNU dynamic linker. Stub version. - Copyright (C) 2003-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -#include <ldsodefs.h> -#include <errno.h> - -/* There is no portable way to know the bounds of the initial thread's stack - so as to mprotect it. */ - -int -internal_function -_dl_make_stack_executable (void **stack_endp) -{ - return ENOSYS; -} -rtld_hidden_def (_dl_make_stack_executable) diff --git a/elf/dl-fini.c b/elf/dl-fini.c deleted file mode 100644 index 93b337bea1..0000000000 --- a/elf/dl-fini.c +++ /dev/null @@ -1,281 +0,0 @@ -/* Call the termination functions of loaded shared objects. - Copyright (C) 1995-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -#include <assert.h> -#include <string.h> -#include <ldsodefs.h> - - -/* Type of the constructor functions. */ -typedef void (*fini_t) (void); - - -void -internal_function -_dl_sort_fini (struct link_map **maps, size_t nmaps, char *used, Lmid_t ns) -{ - /* A list of one element need not be sorted. */ - if (nmaps == 1) - return; - - /* We can skip looking for the binary itself which is at the front - of the search list for the main namespace. */ - unsigned int i = ns == LM_ID_BASE; - uint16_t seen[nmaps]; - memset (seen, 0, nmaps * sizeof (seen[0])); - while (1) - { - /* Keep track of which object we looked at this round. */ - ++seen[i]; - struct link_map *thisp = maps[i]; - - /* Do not handle ld.so in secondary namespaces and object which - are not removed. */ - if (thisp != thisp->l_real || thisp->l_idx == -1) - goto skip; - - /* Find the last object in the list for which the current one is - a dependency and move the current object behind the object - with the dependency. */ - unsigned int k = nmaps - 1; - while (k > i) - { - struct link_map **runp = maps[k]->l_initfini; - if (runp != NULL) - /* Look through the dependencies of the object. */ - while (*runp != NULL) - if (__glibc_unlikely (*runp++ == thisp)) - { - move: - /* Move the current object to the back past the last - object with it as the dependency. */ - memmove (&maps[i], &maps[i + 1], - (k - i) * sizeof (maps[0])); - maps[k] = thisp; - - if (used != NULL) - { - char here_used = used[i]; - memmove (&used[i], &used[i + 1], - (k - i) * sizeof (used[0])); - used[k] = here_used; - } - - if (seen[i + 1] > nmaps - i) - { - ++i; - goto next_clear; - } - - uint16_t this_seen = seen[i]; - memmove (&seen[i], &seen[i + 1], (k - i) * sizeof (seen[0])); - seen[k] = this_seen; - - goto next; - } - - 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 (__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 (__glibc_unlikely (*runp++ == maps[k])) - goto ignore; - goto move; - } - ignore:; - } - - --k; - } - - skip: - if (++i == nmaps) - break; - next_clear: - memset (&seen[i], 0, (nmaps - i) * sizeof (seen[0])); - - next:; - } -} - - -void -internal_function -_dl_fini (void) -{ - /* Lots of fun ahead. We have to call the destructors for all still - loaded objects, in all namespaces. The problem is that the ELF - specification now demands that dependencies between the modules - are taken into account. I.e., the destructor for a module is - called before the ones for any of its dependencies. - - To make things more complicated, we cannot simply use the reverse - order of the constructors. Since the user might have loaded objects - using `dlopen' there are possibly several other modules with its - dependencies to be taken into account. Therefore we have to start - determining the order of the modules once again from the beginning. */ - - /* We run the destructors of the main namespaces last. As for the - other namespaces, we pick run the destructors in them in reverse - order of the namespace ID. */ -#ifdef SHARED - int do_audit = 0; - again: -#endif - for (Lmid_t ns = GL(dl_nns) - 1; ns >= 0; --ns) - { - /* Protect against concurrent loads and unloads. */ - __rtld_lock_lock_recursive (GL(dl_load_lock)); - - unsigned int nloaded = GL(dl_ns)[ns]._ns_nloaded; - /* No need to do anything for empty namespaces or those used for - auditing DSOs. */ - if (nloaded == 0 -#ifdef SHARED - || GL(dl_ns)[ns]._ns_loaded->l_auditing != do_audit -#endif - ) - __rtld_lock_unlock_recursive (GL(dl_load_lock)); - else - { - /* Now we can allocate an array to hold all the pointers and - copy the pointers in. */ - struct link_map *maps[nloaded]; - - unsigned int i; - struct link_map *l; - assert (nloaded != 0 || GL(dl_ns)[ns]._ns_loaded == NULL); - for (l = GL(dl_ns)[ns]._ns_loaded, i = 0; l != NULL; l = l->l_next) - /* Do not handle ld.so in secondary namespaces. */ - if (l == l->l_real) - { - assert (i < nloaded); - - maps[i] = l; - l->l_idx = i; - ++i; - - /* Bump l_direct_opencount of all objects so that they - are not dlclose()ed from underneath us. */ - ++l->l_direct_opencount; - } - assert (ns != LM_ID_BASE || i == nloaded); - assert (ns == LM_ID_BASE || i == nloaded || i == nloaded - 1); - unsigned int nmaps = i; - - /* Now we have to do the sorting. */ - _dl_sort_fini (maps, nmaps, NULL, ns); - - /* We do not rely on the linked list of loaded object anymore - from this point on. We have our own list here (maps). The - various members of this list cannot vanish since the open - count is too high and will be decremented in this loop. So - we release the lock so that some code which might be called - from a destructor can directly or indirectly access the - lock. */ - __rtld_lock_unlock_recursive (GL(dl_load_lock)); - - /* 'maps' now contains the objects in the right order. Now - call the destructors. We have to process this array from - the front. */ - for (i = 0; i < nmaps; ++i) - { - struct link_map *l = maps[i]; - - if (l->l_init_called) - { - /* Make sure nothing happens if we are called twice. */ - l->l_init_called = 0; - - /* Is there a destructor function? */ - if (l->l_info[DT_FINI_ARRAY] != NULL - || l->l_info[DT_FINI] != NULL) - { - /* When debugging print a message first. */ - if (__builtin_expect (GLRO(dl_debug_mask) - & DL_DEBUG_IMPCALLS, 0)) - _dl_debug_printf ("\ncalling fini: %s [%lu]\n\n", - DSO_FILENAME (l->l_name), - ns); - - /* First see whether an array is given. */ - if (l->l_info[DT_FINI_ARRAY] != NULL) - { - ElfW(Addr) *array = - (ElfW(Addr) *) (l->l_addr - + l->l_info[DT_FINI_ARRAY]->d_un.d_ptr); - unsigned int i = (l->l_info[DT_FINI_ARRAYSZ]->d_un.d_val - / sizeof (ElfW(Addr))); - while (i-- > 0) - ((fini_t) array[i]) (); - } - - /* Next try the old-style destructor. */ - if (l->l_info[DT_FINI] != NULL) - DL_CALL_DT_FINI - (l, l->l_addr + l->l_info[DT_FINI]->d_un.d_ptr); - } - -#ifdef SHARED - /* Auditing checkpoint: another object closed. */ - if (!do_audit && __builtin_expect (GLRO(dl_naudit) > 0, 0)) - { - struct audit_ifaces *afct = GLRO(dl_audit); - for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) - { - if (afct->objclose != NULL) - /* Return value is ignored. */ - (void) afct->objclose (&l->l_audit[cnt].cookie); - - afct = afct->next; - } - } -#endif - } - - /* Correct the previous increment. */ - --l->l_direct_opencount; - } - } - } - -#ifdef SHARED - if (! do_audit && GLRO(dl_naudit) > 0) - { - do_audit = 1; - goto again; - } - - 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", - GL(dl_num_relocations), - GL(dl_num_cache_relocations)); -#endif -} diff --git a/elf/dl-fptr.c b/elf/dl-fptr.c deleted file mode 100644 index bf8ae43b51..0000000000 --- a/elf/dl-fptr.c +++ /dev/null @@ -1,322 +0,0 @@ -/* Manage function descriptors. Generic version. - Copyright (C) 1999-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -#include <libintl.h> -#include <unistd.h> -#include <string.h> -#include <sys/param.h> -#include <sys/mman.h> -#include <link.h> -#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 -/* ELF_MACHINE_BOOT_FPTR_TABLE_LEN should be greater than the number of - dynamic symbols in ld.so. */ -# define ELF_MACHINE_BOOT_FPTR_TABLE_LEN 256 -#endif - -#ifndef ELF_MACHINE_LOAD_ADDRESS -# error "ELF_MACHINE_LOAD_ADDRESS is not defined." -#endif - -#ifndef COMPARE_AND_SWAP -# define COMPARE_AND_SWAP(ptr, old, new) \ - (catomic_compare_and_exchange_bool_acq (ptr, new, old) == 0) -#endif - -ElfW(Addr) _dl_boot_fptr_table [ELF_MACHINE_BOOT_FPTR_TABLE_LEN]; - -static struct local - { - struct fdesc_table *root; - struct fdesc *free_list; - unsigned int npages; /* # of pages to allocate */ - /* the next to members MUST be consecutive! */ - struct fdesc_table boot_table; - struct fdesc boot_fdescs[1024]; - } -local = - { - .root = &local.boot_table, - .npages = 2, - .boot_table = - { - .len = sizeof (local.boot_fdescs) / sizeof (local.boot_fdescs[0]), - .first_unused = 0 - } - }; - -/* Create a new fdesc table and return a pointer to the first fdesc - entry. The fdesc lock must have been acquired already. */ - -static struct fdesc_table * -new_fdesc_table (struct local *l, size_t *size) -{ - size_t old_npages = l->npages; - size_t new_npages = old_npages + old_npages; - struct fdesc_table *new_table; - - /* If someone has just created a new table, we return NULL to tell - the caller to use the new table. */ - if (! COMPARE_AND_SWAP (&l->npages, old_npages, new_npages)) - return (struct fdesc_table *) NULL; - - *size = old_npages * GLRO(dl_pagesize); - new_table = __mmap (NULL, *size, - PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0); - if (new_table == MAP_FAILED) - _dl_signal_error (errno, NULL, NULL, - N_("cannot map pages for fdesc table")); - - new_table->len - = (*size - sizeof (*new_table)) / sizeof (struct fdesc); - new_table->first_unused = 1; - return new_table; -} - - -static ElfW(Addr) -make_fdesc (ElfW(Addr) ip, ElfW(Addr) gp) -{ - struct fdesc *fdesc = NULL; - struct fdesc_table *root; - unsigned int old; - struct local *l; - - ELF_MACHINE_LOAD_ADDRESS (l, local); - - retry: - root = l->root; - while (1) - { - old = root->first_unused; - if (old >= root->len) - break; - else if (COMPARE_AND_SWAP (&root->first_unused, old, old + 1)) - { - fdesc = &root->fdesc[old]; - goto install; - } - } - - if (l->free_list) - { - /* Get it from free-list. */ - do - { - fdesc = l->free_list; - if (fdesc == NULL) - goto retry; - } - while (! COMPARE_AND_SWAP ((ElfW(Addr) *) &l->free_list, - (ElfW(Addr)) fdesc, fdesc->ip)); - } - else - { - /* Create a new fdesc table. */ - size_t size; - struct fdesc_table *new_table = new_fdesc_table (l, &size); - - if (new_table == NULL) - goto retry; - - new_table->next = root; - if (! COMPARE_AND_SWAP ((ElfW(Addr) *) &l->root, - (ElfW(Addr)) root, - (ElfW(Addr)) new_table)) - { - /* Someone has just installed a new table. Return NULL to - tell the caller to use the new table. */ - __munmap (new_table, size); - goto retry; - } - - /* Note that the first entry was reserved while allocating the - memory for the new page. */ - fdesc = &new_table->fdesc[0]; - } - - install: - fdesc->ip = ip; - fdesc->gp = gp; - - return (ElfW(Addr)) fdesc; -} - - -static inline ElfW(Addr) * __attribute__ ((always_inline)) -make_fptr_table (struct link_map *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]); - ElfW(Addr) *fptr_table; - size_t size; - size_t len; - - /* XXX Apparently the only way to find out the size of the dynamic - symbol section is to assume that the string table follows right - afterwards... */ - len = ((strtab - (char *) symtab) - / map->l_info[DT_SYMENT]->d_un.d_val); - size = ((len * sizeof (fptr_table[0]) + GLRO(dl_pagesize) - 1) - & -GLRO(dl_pagesize)); - /* XXX We don't support here in the moment systems without MAP_ANON. - There probably are none for IA-64. In case this is proven wrong - we will have to open /dev/null here and use the file descriptor - instead of the hard-coded -1. */ - fptr_table = __mmap (NULL, size, - PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, - -1, 0); - if (fptr_table == MAP_FAILED) - _dl_signal_error (errno, NULL, NULL, - N_("cannot map pages for fptr table")); - - if (COMPARE_AND_SWAP ((ElfW(Addr) *) &map->l_mach.fptr_table, - (ElfW(Addr)) NULL, (ElfW(Addr)) fptr_table)) - map->l_mach.fptr_table_len = len; - else - __munmap (fptr_table, len * sizeof (fptr_table[0])); - - return map->l_mach.fptr_table; -} - - -ElfW(Addr) -_dl_make_fptr (struct link_map *map, const ElfW(Sym) *sym, - ElfW(Addr) ip) -{ - ElfW(Addr) *ftab = map->l_mach.fptr_table; - const ElfW(Sym) *symtab; - Elf_Symndx symidx; - struct local *l; - - if (__glibc_unlikely (ftab == NULL)) - ftab = make_fptr_table (map); - - symtab = (const void *) D_PTR (map, l_info[DT_SYMTAB]); - symidx = sym - symtab; - - if (symidx >= map->l_mach.fptr_table_len) - _dl_signal_error (0, NULL, NULL, - N_("internal error: symidx out of range of fptr table")); - - while (ftab[symidx] == 0) - { - /* GOT has already been relocated in elf_get_dynamic_info - - don't try to relocate it again. */ - ElfW(Addr) fdesc - = make_fdesc (ip, map->l_info[DT_PLTGOT]->d_un.d_ptr); - - if (__builtin_expect (COMPARE_AND_SWAP (&ftab[symidx], (ElfW(Addr)) NULL, - fdesc), 1)) - { - /* Noone has updated the entry and the new function - descriptor has been installed. */ -#if 0 - const char *strtab - = (const void *) D_PTR (map, l_info[DT_STRTAB]); - - ELF_MACHINE_LOAD_ADDRESS (l, local); - if (l->root != &l->boot_table - || l->boot_table.first_unused > 20) - _dl_debug_printf ("created fdesc symbol `%s' at %lx\n", - strtab + sym->st_name, ftab[symidx]); -#endif - break; - } - else - { - /* We created a duplicated function descriptor. We put it on - free-list. */ - struct fdesc *f = (struct fdesc *) fdesc; - - ELF_MACHINE_LOAD_ADDRESS (l, local); - - do - f->ip = (ElfW(Addr)) l->free_list; - while (! COMPARE_AND_SWAP ((ElfW(Addr) *) &l->free_list, - f->ip, fdesc)); - } - } - - return ftab[symidx]; -} - - -void -_dl_unmap (struct link_map *map) -{ - ElfW(Addr) *ftab = map->l_mach.fptr_table; - struct fdesc *head = NULL, *tail = NULL; - size_t i; - - _dl_unmap_segments (map); - - if (ftab == NULL) - return; - - /* String together the fdesc structures that are being freed. */ - for (i = 0; i < map->l_mach.fptr_table_len; ++i) - { - if (ftab[i]) - { - *(struct fdesc **) ftab[i] = head; - head = (struct fdesc *) ftab[i]; - if (tail == NULL) - tail = head; - } - } - - /* Prepend the new list to the free_list: */ - if (tail) - do - tail->ip = (ElfW(Addr)) local.free_list; - while (! COMPARE_AND_SWAP ((ElfW(Addr) *) &local.free_list, - tail->ip, (ElfW(Addr)) head)); - - __munmap (ftab, (map->l_mach.fptr_table_len - * sizeof (map->l_mach.fptr_table[0]))); - - map->l_mach.fptr_table = NULL; -} - - -ElfW(Addr) -_dl_lookup_address (const void *address) -{ - ElfW(Addr) addr = (ElfW(Addr)) address; - struct fdesc_table *t; - unsigned long int i; - - for (t = local.root; t != NULL; t = t->next) - { - i = (struct fdesc *) addr - &t->fdesc[0]; - if (i < t->first_unused && addr == (ElfW(Addr)) &t->fdesc[i]) - { - addr = t->fdesc[i].ip; - break; - } - } - - return addr; -} diff --git a/elf/dl-hwcaps.c b/elf/dl-hwcaps.c deleted file mode 100644 index ac50fd2c38..0000000000 --- a/elf/dl-hwcaps.c +++ /dev/null @@ -1,297 +0,0 @@ -/* Hardware capability support for run-time dynamic loader. - Copyright (C) 2012-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -#include <assert.h> -#include <elf.h> -#include <errno.h> -#include <libintl.h> -#include <unistd.h> -#include <ldsodefs.h> - -#include <dl-procinfo.h> -#include <dl-hwcaps.h> - -#ifdef _DL_FIRST_PLATFORM -# define _DL_FIRST_EXTRA (_DL_FIRST_PLATFORM + _DL_PLATFORMS_COUNT) -#else -# define _DL_FIRST_EXTRA _DL_HWCAP_COUNT -#endif - -/* Return an array of useful/necessary hardware capability names. */ -const struct r_strlenpair * -internal_function -_dl_important_hwcaps (const char *platform, size_t platform_len, size_t *sz, - size_t *max_capstrlen) -{ - uint64_t hwcap_mask = GET_HWCAP_MASK(); - /* Determine how many important bits are set. */ - uint64_t masked = GLRO(dl_hwcap) & hwcap_mask; - size_t cnt = platform != NULL; - size_t n, m; - size_t total; - struct r_strlenpair *result; - struct r_strlenpair *rp; - char *cp; - - /* Count the number of bits set in the masked value. */ - for (n = 0; (~((1ULL << n) - 1) & masked) != 0; ++n) - if ((masked & (1ULL << n)) != 0) - ++cnt; - -#ifdef NEED_DL_SYSINFO_DSO - /* The system-supplied DSO can contain a note of type 2, vendor "GNU". - This gives us a list of names to treat as fake hwcap bits. */ - - const char *dsocaps = NULL; - size_t dsocapslen = 0; - if (GLRO(dl_sysinfo_map) != NULL) - { - const ElfW(Phdr) *const phdr = GLRO(dl_sysinfo_map)->l_phdr; - const ElfW(Word) phnum = GLRO(dl_sysinfo_map)->l_phnum; - for (uint_fast16_t i = 0; i < phnum; ++i) - if (phdr[i].p_type == PT_NOTE) - { - const ElfW(Addr) start = (phdr[i].p_vaddr - + GLRO(dl_sysinfo_map)->l_addr); - /* The standard ELF note layout is exactly as the anonymous struct. - The next element is a variable length vendor name of length - VENDORLEN (with a real length rounded to ElfW(Word)), followed - by the data of length DATALEN (with a real length rounded to - ElfW(Word)). */ - const struct - { - ElfW(Word) vendorlen; - ElfW(Word) datalen; - ElfW(Word) type; - } *note = (const void *) start; - while ((ElfW(Addr)) (note + 1) - start < phdr[i].p_memsz) - { -#define ROUND(len) (((len) + sizeof (ElfW(Word)) - 1) & -sizeof (ElfW(Word))) - /* The layout of the type 2, vendor "GNU" note is as follows: - .long <Number of capabilities enabled by this note> - .long <Capabilities mask> (as mask >> _DL_FIRST_EXTRA). - .byte <The bit number for the next capability> - .asciz <The name of the capability>. */ - if (note->type == NT_GNU_HWCAP - && note->vendorlen == sizeof "GNU" - && !memcmp ((note + 1), "GNU", sizeof "GNU") - && note->datalen > 2 * sizeof (ElfW(Word)) + 2) - { - const ElfW(Word) *p = ((const void *) (note + 1) - + ROUND (sizeof "GNU")); - cnt += *p++; - ++p; /* Skip mask word. */ - dsocaps = (const char *) p; /* Pseudo-string "<b>name" */ - dsocapslen = note->datalen - sizeof *p * 2; - break; - } - note = ((const void *) (note + 1) - + ROUND (note->vendorlen) + ROUND (note->datalen)); -#undef ROUND - } - if (dsocaps != NULL) - break; - } - } -#endif - - /* For TLS enabled builds always add 'tls'. */ - ++cnt; - - /* Create temporary data structure to generate result table. */ - struct r_strlenpair temp[cnt]; - m = 0; -#ifdef NEED_DL_SYSINFO_DSO - if (dsocaps != NULL) - { - /* dsocaps points to the .asciz string, and -1 points to the mask - .long just before the string. */ - const ElfW(Word) mask = ((const ElfW(Word) *) dsocaps)[-1]; - GLRO(dl_hwcap) |= (uint64_t) mask << _DL_FIRST_EXTRA; - /* Note that we add the dsocaps to the set already chosen by the - LD_HWCAP_MASK environment variable (or default HWCAP_IMPORTANT). - So there is no way to request ignoring an OS-supplied dsocap - string and bit like you can ignore an OS-supplied HWCAP bit. */ - hwcap_mask |= (uint64_t) mask << _DL_FIRST_EXTRA; -#if HAVE_TUNABLES - TUNABLE_SET (glibc, tune, hwcap_mask, uint64_t, hwcap_mask); -#else - GLRO(dl_hwcap_mask) = hwcap_mask; -#endif - size_t len; - for (const char *p = dsocaps; p < dsocaps + dsocapslen; p += len + 1) - { - uint_fast8_t bit = *p++; - len = strlen (p); - - /* Skip entries that are not enabled in the mask word. */ - if (__glibc_likely (mask & ((ElfW(Word)) 1 << bit))) - { - temp[m].str = p; - temp[m].len = len; - ++m; - } - else - --cnt; - } - } -#endif - for (n = 0; masked != 0; ++n) - if ((masked & (1ULL << n)) != 0) - { - temp[m].str = _dl_hwcap_string (n); - temp[m].len = strlen (temp[m].str); - masked ^= 1ULL << n; - ++m; - } - if (platform != NULL) - { - temp[m].str = platform; - temp[m].len = platform_len; - ++m; - } - - temp[m].str = "tls"; - temp[m].len = 3; - ++m; - - assert (m == cnt); - - /* Determine the total size of all strings together. */ - if (cnt == 1) - total = temp[0].len + 1; - else - { - total = temp[0].len + temp[cnt - 1].len + 2; - if (cnt > 2) - { - total <<= 1; - for (n = 1; n + 1 < cnt; ++n) - total += temp[n].len + 1; - if (cnt > 3 - && (cnt >= sizeof (size_t) * 8 - || total + (sizeof (*result) << 3) - >= (1UL << (sizeof (size_t) * 8 - cnt + 3)))) - _dl_signal_error (ENOMEM, NULL, NULL, - N_("cannot create capability list")); - - total <<= cnt - 3; - } - } - - /* The result structure: we use a very compressed way to store the - various combinations of capability names. */ - *sz = 1 << cnt; - result = (struct r_strlenpair *) malloc (*sz * sizeof (*result) + total); - if (result == NULL) - _dl_signal_error (ENOMEM, NULL, NULL, - N_("cannot create capability list")); - - if (cnt == 1) - { - result[0].str = (char *) (result + *sz); - result[0].len = temp[0].len + 1; - result[1].str = (char *) (result + *sz); - result[1].len = 0; - cp = __mempcpy ((char *) (result + *sz), temp[0].str, temp[0].len); - *cp = '/'; - *sz = 2; - *max_capstrlen = result[0].len; - - return result; - } - - /* Fill in the information. This follows the following scheme - (indices from TEMP for four strings): - entry #0: 0, 1, 2, 3 binary: 1111 - #1: 0, 1, 3 1101 - #2: 0, 2, 3 1011 - #3: 0, 3 1001 - This allows the representation of all possible combinations of - capability names in the string. First generate the strings. */ - result[1].str = result[0].str = cp = (char *) (result + *sz); -#define add(idx) \ - cp = __mempcpy (__mempcpy (cp, temp[idx].str, temp[idx].len), "/", 1); - if (cnt == 2) - { - add (1); - add (0); - } - else - { - n = 1 << (cnt - 1); - do - { - n -= 2; - - /* We always add the last string. */ - add (cnt - 1); - - /* Add the strings which have the bit set in N. */ - for (m = cnt - 2; m > 0; --m) - if ((n & (1 << m)) != 0) - add (m); - - /* Always add the first string. */ - add (0); - } - while (n != 0); - } -#undef add - - /* Now we are ready to install the string pointers and length. */ - for (n = 0; n < (1UL << cnt); ++n) - result[n].len = 0; - n = cnt; - do - { - size_t mask = 1 << --n; - - rp = result; - for (m = 1 << cnt; m > 0; ++rp) - if ((--m & mask) != 0) - rp->len += temp[n].len + 1; - } - while (n != 0); - - /* The first half of the strings all include the first string. */ - n = (1 << cnt) - 2; - rp = &result[2]; - while (n != (1UL << (cnt - 1))) - { - if ((--n & 1) != 0) - rp[0].str = rp[-2].str + rp[-2].len; - else - rp[0].str = rp[-1].str; - ++rp; - } - - /* The second half starts right after the first part of the string of - the corresponding entry in the first half. */ - do - { - rp[0].str = rp[-(1 << (cnt - 1))].str + temp[cnt - 1].len + 1; - ++rp; - } - while (--n != 0); - - /* The maximum string length. */ - *max_capstrlen = result[0].len; - - return result; -} diff --git a/elf/dl-hwcaps.h b/elf/dl-hwcaps.h deleted file mode 100644 index 2c4fa3db02..0000000000 --- a/elf/dl-hwcaps.h +++ /dev/null @@ -1,30 +0,0 @@ -/* Hardware capability support for run-time dynamic loader. - Copyright (C) 2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -#include <elf/dl-tunables.h> - -#if HAVE_TUNABLES -# define GET_HWCAP_MASK() TUNABLE_GET (glibc, tune, hwcap_mask, uint64_t, NULL) -#else -# ifdef SHARED -# define GET_HWCAP_MASK() GLRO(dl_hwcap_mask) -# else -/* HWCAP_MASK is ignored in static binaries when built without tunables. */ -# define GET_HWCAP_MASK() (0) -# endif -#endif diff --git a/elf/dl-init.c b/elf/dl-init.c deleted file mode 100644 index 5c5f3de365..0000000000 --- a/elf/dl-init.c +++ /dev/null @@ -1,126 +0,0 @@ -/* Run initializers for newly loaded objects. - Copyright (C) 1995-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -#include <stddef.h> -#include <ldsodefs.h> - - -/* Type of the initializer. */ -typedef void (*init_t) (int, char **, char **); - - -static void -call_init (struct link_map *l, int argc, char **argv, char **env) -{ - if (l->l_init_called) - /* This object is all done. */ - return; - - /* Avoid handling this constructor again in case we have a circular - dependency. */ - l->l_init_called = 1; - - /* Check for object which constructors we do not run here. */ - if (__builtin_expect (l->l_name[0], 'a') == '\0' - && l->l_type == lt_executable) - return; - - /* Are there any constructors? */ - if (l->l_info[DT_INIT] == NULL - && __builtin_expect (l->l_info[DT_INIT_ARRAY] == NULL, 1)) - return; - - /* Print a debug message if wanted. */ - if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_IMPCALLS)) - _dl_debug_printf ("\ncalling init: %s\n\n", - DSO_FILENAME (l->l_name)); - - /* Now run the local constructors. There are two forms of them: - - the one named by DT_INIT - - the others in the DT_INIT_ARRAY. - */ - if (l->l_info[DT_INIT] != NULL) - DL_CALL_DT_INIT(l, l->l_addr + l->l_info[DT_INIT]->d_un.d_ptr, argc, argv, env); - - /* Next see whether there is an array with initialization functions. */ - ElfW(Dyn) *init_array = l->l_info[DT_INIT_ARRAY]; - if (init_array != NULL) - { - unsigned int j; - unsigned int jm; - ElfW(Addr) *addrs; - - jm = l->l_info[DT_INIT_ARRAYSZ]->d_un.d_val / sizeof (ElfW(Addr)); - - addrs = (ElfW(Addr) *) (init_array->d_un.d_ptr + l->l_addr); - for (j = 0; j < jm; ++j) - ((init_t) addrs[j]) (argc, argv, env); - } -} - - -void -internal_function -_dl_init (struct link_map *main_map, int argc, char **argv, char **env) -{ - ElfW(Dyn) *preinit_array = main_map->l_info[DT_PREINIT_ARRAY]; - ElfW(Dyn) *preinit_array_size = main_map->l_info[DT_PREINIT_ARRAYSZ]; - unsigned int i; - - if (__glibc_unlikely (GL(dl_initfirst) != NULL)) - { - call_init (GL(dl_initfirst), argc, argv, env); - GL(dl_initfirst) = NULL; - } - - /* Don't do anything if there is no preinit array. */ - if (__builtin_expect (preinit_array != NULL, 0) - && preinit_array_size != NULL - && (i = preinit_array_size->d_un.d_val / sizeof (ElfW(Addr))) > 0) - { - ElfW(Addr) *addrs; - unsigned int cnt; - - if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_IMPCALLS)) - _dl_debug_printf ("\ncalling preinit: %s\n\n", - DSO_FILENAME (main_map->l_name)); - - addrs = (ElfW(Addr) *) (preinit_array->d_un.d_ptr + main_map->l_addr); - for (cnt = 0; cnt < i; ++cnt) - ((init_t) addrs[cnt]) (argc, argv, env); - } - - /* Stupid users forced the ELF specification to be changed. It now - says that the dynamic loader is responsible for determining the - order in which the constructors have to run. The constructors - for all dependencies of an object must run before the constructor - for the object itself. Circular dependencies are left unspecified. - - This is highly questionable since it puts the burden on the dynamic - loader which has to find the dependencies at runtime instead of - letting the user do it right. Stupidity rules! */ - - i = main_map->l_searchlist.r_nlist; - while (i-- > 0) - call_init (main_map->l_initfini[i], argc, argv, env); - -#ifndef HAVE_INLINED_SYSCALLS - /* Finished starting up. */ - _dl_starting_up = 0; -#endif -} diff --git a/elf/dl-iteratephdr.c b/elf/dl-iteratephdr.c deleted file mode 100644 index ddd5bde831..0000000000 --- a/elf/dl-iteratephdr.c +++ /dev/null @@ -1,89 +0,0 @@ -/* Get loaded objects program headers. - Copyright (C) 2001-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Jakub Jelinek <jakub@redhat.com>, 2001. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public License as - published by the Free Software Foundation; either version 2.1 of the - License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; see the file COPYING.LIB. If - not, see <http://www.gnu.org/licenses/>. */ - -#include <errno.h> -#include <ldsodefs.h> -#include <stddef.h> -#include <libc-lock.h> - -static void -cancel_handler (void *arg __attribute__((unused))) -{ - __rtld_lock_unlock_recursive (GL(dl_load_write_lock)); -} - -hidden_proto (__dl_iterate_phdr) -int -__dl_iterate_phdr (int (*callback) (struct dl_phdr_info *info, - size_t size, void *data), void *data) -{ - struct link_map *l; - struct dl_phdr_info info; - int ret = 0; - - /* Make sure nobody modifies the list of loaded objects. */ - __rtld_lock_lock_recursive (GL(dl_load_write_lock)); - __libc_cleanup_push (cancel_handler, NULL); - - /* We have to determine the namespace of the caller since this determines - which namespace is reported. */ - size_t nloaded = GL(dl_ns)[0]._ns_nloaded; - Lmid_t ns = 0; -#ifdef SHARED - const void *caller = RETURN_ADDRESS (0); - for (Lmid_t cnt = GL(dl_nns) - 1; cnt > 0; --cnt) - for (struct link_map *l = GL(dl_ns)[cnt]._ns_loaded; l; l = l->l_next) - { - /* We have to count the total number of loaded objects. */ - nloaded += GL(dl_ns)[cnt]._ns_nloaded; - - if (caller >= (const void *) l->l_map_start - && caller < (const void *) l->l_map_end - && (l->l_contiguous - || _dl_addr_inside_object (l, (ElfW(Addr)) caller))) - ns = cnt; - } -#endif - - for (l = GL(dl_ns)[ns]._ns_loaded; l != NULL; l = l->l_next) - { - info.dlpi_addr = l->l_real->l_addr; - info.dlpi_name = l->l_real->l_name; - info.dlpi_phdr = l->l_real->l_phdr; - info.dlpi_phnum = l->l_real->l_phnum; - info.dlpi_adds = GL(dl_load_adds); - info.dlpi_subs = GL(dl_load_adds) - nloaded; - info.dlpi_tls_data = NULL; - info.dlpi_tls_modid = l->l_real->l_tls_modid; - if (info.dlpi_tls_modid != 0) - info.dlpi_tls_data = GLRO(dl_tls_get_addr_soft) (l->l_real); - ret = callback (&info, sizeof (struct dl_phdr_info), data); - if (ret) - break; - } - - /* Release the lock. */ - __libc_cleanup_pop (0); - __rtld_lock_unlock_recursive (GL(dl_load_write_lock)); - - return ret; -} -hidden_def (__dl_iterate_phdr) - -weak_alias (__dl_iterate_phdr, dl_iterate_phdr); diff --git a/elf/dl-libc.c b/elf/dl-libc.c deleted file mode 100644 index 9fdc8b1130..0000000000 --- a/elf/dl-libc.c +++ /dev/null @@ -1,330 +0,0 @@ -/* Handle loading and unloading shared objects for internal libc purposes. - Copyright (C) 1999-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Zack Weinberg <zack@rabi.columbia.edu>, 1999. - - 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 <stdlib.h> -#include <ldsodefs.h> - -extern int __libc_argc attribute_hidden; -extern char **__libc_argv attribute_hidden; - -extern char **__environ; - -/* The purpose of this file is to provide wrappers around the dynamic - linker error mechanism (similar to dlopen() et al in libdl) which - are usable from within libc. Generally we want to throw away the - string that dlerror() would return and just pass back a null pointer - for errors. This also lets the rest of libc not know about the error - handling mechanism. - - Much of this code came from gconv_dl.c with slight modifications. */ - -static int -internal_function -dlerror_run (void (*operate) (void *), void *args) -{ - const char *objname; - const char *last_errstring = NULL; - bool malloced; - - int result = (_dl_catch_error (&objname, &last_errstring, &malloced, - operate, args) - ?: last_errstring != NULL); - - if (result && malloced) - free ((char *) last_errstring); - - return result; -} - -/* These functions are called by dlerror_run... */ - -struct do_dlopen_args -{ - /* Argument to do_dlopen. */ - const char *name; - /* Opening mode. */ - int mode; - /* This is the caller of the dlopen() function. */ - const void *caller_dlopen; - - /* Return from do_dlopen. */ - struct link_map *map; -}; - -struct do_dlsym_args -{ - /* Arguments to do_dlsym. */ - struct link_map *map; - const char *name; - - /* Return values of do_dlsym. */ - lookup_t loadbase; - const ElfW(Sym) *ref; -}; - -static void -do_dlopen (void *ptr) -{ - struct do_dlopen_args *args = (struct do_dlopen_args *) ptr; - /* Open and relocate the shared object. */ - args->map = GLRO(dl_open) (args->name, args->mode, args->caller_dlopen, - __LM_ID_CALLER, __libc_argc, __libc_argv, - __environ); -} - -static void -do_dlsym (void *ptr) -{ - struct do_dlsym_args *args = (struct do_dlsym_args *) ptr; - args->ref = NULL; - args->loadbase = GLRO(dl_lookup_symbol_x) (args->name, args->map, &args->ref, - args->map->l_local_scope, NULL, 0, - DL_LOOKUP_RETURN_NEWEST, NULL); -} - -static void -do_dlclose (void *ptr) -{ - GLRO(dl_close) ((struct link_map *) ptr); -} - -/* This code is to support __libc_dlopen from __libc_dlopen'ed shared - libraries. We need to ensure the statically linked __libc_dlopen - etc. functions are used instead of the dynamically loaded. */ -struct dl_open_hook -{ - void *(*dlopen_mode) (const char *name, int mode); - void *(*dlsym) (void *map, const char *name); - int (*dlclose) (void *map); -}; - -#ifdef SHARED -extern struct dl_open_hook *_dl_open_hook; -libc_hidden_proto (_dl_open_hook); -struct dl_open_hook *_dl_open_hook __attribute__ ((nocommon)); -libc_hidden_data_def (_dl_open_hook); -#else -static void -do_dlsym_private (void *ptr) -{ - lookup_t l; - struct r_found_version vers; - vers.name = "GLIBC_PRIVATE"; - vers.hidden = 1; - /* vers.hash = _dl_elf_hash (vers.name); */ - vers.hash = 0x0963cf85; - vers.filename = NULL; - - struct do_dlsym_args *args = (struct do_dlsym_args *) ptr; - args->ref = NULL; - l = GLRO(dl_lookup_symbol_x) (args->name, args->map, &args->ref, - args->map->l_scope, &vers, 0, 0, NULL); - args->loadbase = l; -} - -static struct dl_open_hook _dl_open_hook = - { - .dlopen_mode = __libc_dlopen_mode, - .dlsym = __libc_dlsym, - .dlclose = __libc_dlclose - }; -#endif - -/* ... and these functions call dlerror_run. */ - -void * -__libc_dlopen_mode (const char *name, int mode) -{ - struct do_dlopen_args args; - args.name = name; - args.mode = mode; - args.caller_dlopen = RETURN_ADDRESS (0); - -#ifdef SHARED - 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 - if (dlerror_run (do_dlopen, &args)) - return NULL; - - __libc_register_dl_open_hook (args.map); - __libc_register_dlfcn_hook (args.map); - return (void *) args.map; -#endif -} -libc_hidden_def (__libc_dlopen_mode) - -#ifndef SHARED -void * -__libc_dlsym_private (struct link_map *map, const char *name) -{ - struct do_dlsym_args sargs; - sargs.map = map; - sargs.name = name; - - if (! dlerror_run (do_dlsym_private, &sargs)) - return DL_SYMBOL_ADDRESS (sargs.loadbase, sargs.ref); - return NULL; -} - -void -__libc_register_dl_open_hook (struct link_map *map) -{ - struct dl_open_hook **hook; - - hook = (struct dl_open_hook **) __libc_dlsym_private (map, "_dl_open_hook"); - if (hook != NULL) - *hook = &_dl_open_hook; -} -#endif - -void * -__libc_dlsym (void *map, const char *name) -{ - struct do_dlsym_args args; - args.map = map; - args.name = name; - -#ifdef SHARED - if (__glibc_unlikely (_dl_open_hook != NULL)) - return _dl_open_hook->dlsym (map, name); -#endif - return (dlerror_run (do_dlsym, &args) ? NULL - : (void *) (DL_SYMBOL_ADDRESS (args.loadbase, args.ref))); -} -libc_hidden_def (__libc_dlsym) - -int -__libc_dlclose (void *map) -{ -#ifdef SHARED - if (__glibc_unlikely (_dl_open_hook != NULL)) - return _dl_open_hook->dlclose (map); -#endif - return dlerror_run (do_dlclose, map); -} -libc_hidden_def (__libc_dlclose) - - -static bool __libc_freeres_fn_section -free_slotinfo (struct dtv_slotinfo_list **elemp) -{ - size_t cnt; - - if (*elemp == NULL) - /* Nothing here, all is removed (or there never was anything). */ - return true; - - if (!free_slotinfo (&(*elemp)->next)) - /* We cannot free the entry. */ - return false; - - /* That cleared our next pointer for us. */ - - for (cnt = 0; cnt < (*elemp)->len; ++cnt) - if ((*elemp)->slotinfo[cnt].map != NULL) - /* Still used. */ - return false; - - /* We can remove the list element. */ - free (*elemp); - *elemp = NULL; - - return true; -} - - -libc_freeres_fn (free_mem) -{ - struct link_map *l; - struct r_search_path_elem *d; - - /* Remove all search directories. */ - d = GL(dl_all_dirs); - while (d != GLRO(dl_init_all_dirs)) - { - struct r_search_path_elem *old = d; - d = d->next; - free (old); - } - - for (Lmid_t ns = 0; ns < GL(dl_nns); ++ns) - { - for (l = GL(dl_ns)[ns]._ns_loaded; l != NULL; l = l->l_next) - { - struct libname_list *lnp = l->l_libname->next; - - l->l_libname->next = NULL; - - /* Remove all additional names added to the objects. */ - while (lnp != NULL) - { - struct libname_list *old = lnp; - lnp = lnp->next; - if (! old->dont_free) - free (old); - } - - /* Free the initfini dependency list. */ - if (l->l_free_initfini) - free (l->l_initfini); - l->l_initfini = NULL; - } - - if (__builtin_expect (GL(dl_ns)[ns]._ns_global_scope_alloc, 0) != 0 - && (GL(dl_ns)[ns]._ns_main_searchlist->r_nlist - // XXX Check whether we need NS-specific initial_searchlist - == GLRO(dl_initial_searchlist).r_nlist)) - { - /* All object dynamically loaded by the program are unloaded. Free - the memory allocated for the global scope variable. */ - struct link_map **old = GL(dl_ns)[ns]._ns_main_searchlist->r_list; - - /* Put the old map in. */ - GL(dl_ns)[ns]._ns_main_searchlist->r_list - // XXX Check whether we need NS-specific initial_searchlist - = GLRO(dl_initial_searchlist).r_list; - /* Signal that the original map is used. */ - GL(dl_ns)[ns]._ns_global_scope_alloc = 0; - - /* Now free the old map. */ - free (old); - } - } - - /* Free the memory allocated for the dtv slotinfo array. We can do - this only if all modules which used this memory are unloaded. */ -#ifdef SHARED - if (GL(dl_initial_dtv) == NULL) - /* There was no initial TLS setup, it was set up later when - it used the normal malloc. */ - free_slotinfo (&GL(dl_tls_dtv_slotinfo_list)); - else -#endif - /* The first element of the list does not have to be deallocated. - It was allocated in the dynamic linker (i.e., with a different - malloc), and in the static library it's in .bss space. */ - free_slotinfo (&GL(dl_tls_dtv_slotinfo_list)->next); - - void *scope_free_list = GL(dl_scope_free_list); - GL(dl_scope_free_list) = NULL; - free (scope_free_list); -} diff --git a/elf/dl-load.c b/elf/dl-load.c deleted file mode 100644 index c1b6d4ba0f..0000000000 --- a/elf/dl-load.c +++ /dev/null @@ -1,2307 +0,0 @@ -/* Map in a shared object's segments from the file. - Copyright (C) 1995-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -#include <elf.h> -#include <errno.h> -#include <fcntl.h> -#include <libintl.h> -#include <stdbool.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <ldsodefs.h> -#include <bits/wordsize.h> -#include <sys/mman.h> -#include <sys/param.h> -#include <sys/stat.h> -#include <sys/types.h> -#include "dynamic-link.h" -#include <abi-tag.h> -#include <stackinfo.h> -#include <caller.h> -#include <sysdep.h> -#include <stap-probe.h> -#include <libc-pointer-arith.h> - -#include <dl-dst.h> -#include <dl-load.h> -#include <dl-map-segments.h> -#include <dl-unmap-segments.h> -#include <dl-machine-reject-phdr.h> -#include <dl-sysdep-open.h> - - -#include <endian.h> -#if BYTE_ORDER == BIG_ENDIAN -# define byteorder ELFDATA2MSB -#elif BYTE_ORDER == LITTLE_ENDIAN -# define byteorder ELFDATA2LSB -#else -# error "Unknown BYTE_ORDER " BYTE_ORDER -# define byteorder ELFDATANONE -#endif - -#define STRING(x) __STRING (x) - - -int __stack_prot attribute_hidden attribute_relro -#if _STACK_GROWS_DOWN && defined PROT_GROWSDOWN - = PROT_GROWSDOWN; -#elif _STACK_GROWS_UP && defined PROT_GROWSUP - = PROT_GROWSUP; -#else - = 0; -#endif - - -/* Type for the buffer we put the ELF header and hopefully the program - header. This buffer does not really have to be too large. In most - cases the program header follows the ELF header directly. If this - is not the case all bets are off and we can make the header - arbitrarily large and still won't get it read. This means the only - question is how large are the ELF and program header combined. The - ELF header 32-bit files is 52 bytes long and in 64-bit files is 64 - bytes long. Each program header entry is again 32 and 56 bytes - long respectively. I.e., even with a file which has 10 program - header entries we only have to read 372B/624B respectively. Add to - this a bit of margin for program notes and reading 512B and 832B - for 32-bit and 64-bit files respecitvely is enough. If this - heuristic should really fail for some file the code in - `_dl_map_object_from_fd' knows how to recover. */ -struct filebuf -{ - ssize_t len; -#if __WORDSIZE == 32 -# define FILEBUF_SIZE 512 -#else -# define FILEBUF_SIZE 832 -#endif - char buf[FILEBUF_SIZE] __attribute__ ((aligned (__alignof (ElfW(Ehdr))))); -}; - -/* This is the decomposed LD_LIBRARY_PATH search path. */ -static struct r_search_path_struct env_path_list attribute_relro; - -/* List of the hardware capabilities we might end up using. */ -static const struct r_strlenpair *capstr attribute_relro; -static size_t ncapstr attribute_relro; -static size_t max_capstrlen attribute_relro; - - -/* Get the generated information about the trusted directories. */ -#include "trusted-dirs.h" - -static const char system_dirs[] = SYSTEM_DIRS; -static const size_t system_dirs_len[] = -{ - SYSTEM_DIRS_LEN -}; -#define nsystem_dirs_len \ - (sizeof (system_dirs_len) / sizeof (system_dirs_len[0])) - - -static bool -is_trusted_path (const char *path, size_t len) -{ - const char *trun = system_dirs; - - for (size_t idx = 0; idx < nsystem_dirs_len; ++idx) - { - if (len == system_dirs_len[idx] && memcmp (trun, path, len) == 0) - /* Found it. */ - return true; - - trun += system_dirs_len[idx] + 1; - } - - return false; -} - - -static bool -is_trusted_path_normalize (const char *path, size_t len) -{ - if (len == 0) - return false; - - if (*path == ':') - { - ++path; - --len; - } - - char *npath = (char *) alloca (len + 2); - char *wnp = npath; - while (*path != '\0') - { - if (path[0] == '/') - { - if (path[1] == '.') - { - if (path[2] == '.' && (path[3] == '/' || path[3] == '\0')) - { - while (wnp > npath && *--wnp != '/') - ; - path += 3; - continue; - } - else if (path[2] == '/' || path[2] == '\0') - { - path += 2; - continue; - } - } - - if (wnp > npath && wnp[-1] == '/') - { - ++path; - continue; - } - } - - *wnp++ = *path++; - } - - if (wnp == npath || wnp[-1] != '/') - *wnp++ = '/'; - - const char *trun = system_dirs; - - for (size_t idx = 0; idx < nsystem_dirs_len; ++idx) - { - if (wnp - npath >= system_dirs_len[idx] - && memcmp (trun, npath, system_dirs_len[idx]) == 0) - /* Found it. */ - return true; - - trun += system_dirs_len[idx] + 1; - } - - return false; -} - - -static size_t -is_dst (const char *start, const char *name, const char *str, - int is_path, int secure) -{ - size_t len; - bool is_curly = false; - - if (name[0] == '{') - { - is_curly = true; - ++name; - } - - len = 0; - while (name[len] == str[len] && name[len] != '\0') - ++len; - - if (is_curly) - { - if (name[len] != '}') - return 0; - - /* Point again at the beginning of the name. */ - --name; - /* Skip over closing curly brace and adjust for the --name. */ - len += 2; - } - else if (name[len] != '\0' && name[len] != '/' - && (!is_path || name[len] != ':')) - return 0; - - if (__glibc_unlikely (secure) - && ((name[len] != '\0' && name[len] != '/' - && (!is_path || name[len] != ':')) - || (name != start + 1 && (!is_path || name[-2] != ':')))) - return 0; - - return len; -} - - -size_t -_dl_dst_count (const char *name, int is_path) -{ - const char *const start = name; - size_t cnt = 0; - - do - { - size_t len; - - /* $ORIGIN is not expanded for SUID/GUID programs (except if it - is $ORIGIN alone) and it must always appear first in path. */ - ++name; - if ((len = is_dst (start, name, "ORIGIN", is_path, - __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; - - name = strchr (name + len, '$'); - } - while (name != NULL); - - return cnt; -} - - -char * -_dl_dst_substitute (struct link_map *l, const char *name, char *result, - int is_path) -{ - const char *const start = name; - - /* Now fill the result path. While copying over the string we keep - track of the start of the last path element. When we come across - a DST we copy over the value or (if the value is not available) - leave the entire path element out. */ - char *wp = result; - char *last_elem = result; - bool check_for_trusted = false; - - do - { - if (__glibc_unlikely (*name == '$')) - { - const char *repl = NULL; - size_t len; - - ++name; - if ((len = is_dst (start, name, "ORIGIN", is_path, - __libc_enable_secure)) != 0) - { - repl = l->l_origin; - check_for_trusted = (__libc_enable_secure - && l->l_type == lt_executable); - } - else if ((len = is_dst (start, name, "PLATFORM", is_path, 0)) != 0) - repl = GLRO(dl_platform); - else if ((len = is_dst (start, name, "LIB", is_path, 0)) != 0) - repl = DL_DST_LIB; - - if (repl != NULL && repl != (const char *) -1) - { - wp = __stpcpy (wp, repl); - name += len; - } - else if (len > 1) - { - /* We cannot use this path element, the value of the - replacement is unknown. */ - wp = last_elem; - name += len; - while (*name != '\0' && (!is_path || *name != ':')) - ++name; - /* Also skip following colon if this is the first rpath - element, but keep an empty element at the end. */ - if (wp == result && is_path && *name == ':' && name[1] != '\0') - ++name; - } - else - /* No DST we recognize. */ - *wp++ = '$'; - } - else - { - *wp++ = *name++; - if (is_path && *name == ':') - { - /* In SUID/SGID programs, after $ORIGIN expansion the - normalized path must be rooted in one of the trusted - directories. */ - if (__glibc_unlikely (check_for_trusted) - && !is_trusted_path_normalize (last_elem, wp - last_elem)) - wp = last_elem; - else - last_elem = wp; - - check_for_trusted = false; - } - } - } - while (*name != '\0'); - - /* In SUID/SGID programs, after $ORIGIN expansion the normalized - path must be rooted in one of the trusted directories. */ - if (__glibc_unlikely (check_for_trusted) - && !is_trusted_path_normalize (last_elem, wp - last_elem)) - wp = last_elem; - - *wp = '\0'; - - return result; -} - - -/* Return copy of argument with all recognized dynamic string tokens - ($ORIGIN and $PLATFORM for now) replaced. On some platforms it - might not be possible to determine the path from which the object - belonging to the map is loaded. In this case the path element - containing $ORIGIN is left out. */ -static char * -expand_dynamic_string_token (struct link_map *l, const char *s, int is_path) -{ - /* We make two runs over the string. First we determine how large the - resulting string is and then we copy it over. Since this is no - frequently executed operation we are looking here not for performance - but rather for code size. */ - size_t cnt; - size_t total; - char *result; - - /* Determine the number of DST elements. */ - cnt = DL_DST_COUNT (s, is_path); - - /* If we do not have to replace anything simply copy the string. */ - if (__glibc_likely (cnt == 0)) - return __strdup (s); - - /* Determine the length of the substituted string. */ - total = DL_DST_REQUIRED (l, s, strlen (s), cnt); - - /* Allocate the necessary memory. */ - result = (char *) malloc (total + 1); - if (result == NULL) - return NULL; - - return _dl_dst_substitute (l, s, result, is_path); -} - - -/* Add `name' to the list of names for a particular shared object. - `name' is expected to have been allocated with malloc and will - be freed if the shared object already has this name. - Returns false if the object already had this name. */ -static void -internal_function -add_name_to_object (struct link_map *l, const char *name) -{ - struct libname_list *lnp, *lastp; - struct libname_list *newname; - size_t name_len; - - lastp = NULL; - for (lnp = l->l_libname; lnp != NULL; lastp = lnp, lnp = lnp->next) - if (strcmp (name, lnp->name) == 0) - return; - - name_len = strlen (name) + 1; - newname = (struct libname_list *) malloc (sizeof *newname + name_len); - if (newname == NULL) - { - /* No more memory. */ - _dl_signal_error (ENOMEM, name, NULL, N_("cannot allocate name record")); - return; - } - /* The object should have a libname set from _dl_new_object. */ - assert (lastp != NULL); - - newname->name = memcpy (newname + 1, name, name_len); - newname->next = NULL; - newname->dont_free = 0; - lastp->next = newname; -} - -/* Standard search directories. */ -static struct r_search_path_struct rtld_search_dirs attribute_relro; - -static size_t max_dirnamelen; - -static struct r_search_path_elem ** -fillin_rpath (char *rpath, struct r_search_path_elem **result, const char *sep, - int check_trusted, const char *what, const char *where, - struct link_map *l) -{ - char *cp; - size_t nelems = 0; - char *to_free; - - while ((cp = __strsep (&rpath, sep)) != NULL) - { - struct r_search_path_elem *dirp; - - to_free = cp = expand_dynamic_string_token (l, cp, 1); - - size_t len = strlen (cp); - - /* `strsep' can pass an empty string. This has to be - interpreted as `use the current directory'. */ - if (len == 0) - { - static const char curwd[] = "./"; - cp = (char *) curwd; - } - - /* Remove trailing slashes (except for "/"). */ - while (len > 1 && cp[len - 1] == '/') - --len; - - /* Now add one if there is none so far. */ - if (len > 0 && cp[len - 1] != '/') - cp[len++] = '/'; - - /* Make sure we don't use untrusted directories if we run SUID. */ - if (__glibc_unlikely (check_trusted) && !is_trusted_path (cp, len)) - { - free (to_free); - continue; - } - - /* See if this directory is already known. */ - for (dirp = GL(dl_all_dirs); dirp != NULL; dirp = dirp->next) - if (dirp->dirnamelen == len && memcmp (cp, dirp->dirname, len) == 0) - break; - - if (dirp != NULL) - { - /* It is available, see whether it's on our own list. */ - size_t cnt; - for (cnt = 0; cnt < nelems; ++cnt) - if (result[cnt] == dirp) - break; - - if (cnt == nelems) - result[nelems++] = dirp; - } - else - { - size_t cnt; - enum r_dir_status init_val; - size_t where_len = where ? strlen (where) + 1 : 0; - - /* It's a new directory. Create an entry and add it. */ - dirp = (struct r_search_path_elem *) - malloc (sizeof (*dirp) + ncapstr * sizeof (enum r_dir_status) - + where_len + len + 1); - if (dirp == NULL) - _dl_signal_error (ENOMEM, NULL, NULL, - N_("cannot create cache for search path")); - - dirp->dirname = ((char *) dirp + sizeof (*dirp) - + ncapstr * sizeof (enum r_dir_status)); - *((char *) __mempcpy ((char *) dirp->dirname, cp, len)) = '\0'; - dirp->dirnamelen = len; - - if (len > max_dirnamelen) - max_dirnamelen = len; - - /* We have to make sure all the relative directories are - never ignored. The current directory might change and - all our saved information would be void. */ - init_val = cp[0] != '/' ? existing : unknown; - for (cnt = 0; cnt < ncapstr; ++cnt) - dirp->status[cnt] = init_val; - - dirp->what = what; - if (__glibc_likely (where != NULL)) - dirp->where = memcpy ((char *) dirp + sizeof (*dirp) + len + 1 - + (ncapstr * sizeof (enum r_dir_status)), - where, where_len); - else - dirp->where = NULL; - - dirp->next = GL(dl_all_dirs); - GL(dl_all_dirs) = dirp; - - /* Put it in the result array. */ - result[nelems++] = dirp; - } - free (to_free); - } - - /* Terminate the array. */ - result[nelems] = NULL; - - return result; -} - - -static bool -internal_function -decompose_rpath (struct r_search_path_struct *sps, - const char *rpath, struct link_map *l, const char *what) -{ - /* Make a copy we can work with. */ - const char *where = l->l_name; - char *copy; - char *cp; - struct r_search_path_elem **result; - size_t nelems; - /* Initialize to please the compiler. */ - const char *errstring = NULL; - - /* First see whether we must forget the RUNPATH and RPATH from this - object. */ - if (__glibc_unlikely (GLRO(dl_inhibit_rpath) != NULL) - && !__libc_enable_secure) - { - const char *inhp = GLRO(dl_inhibit_rpath); - - do - { - const char *wp = where; - - while (*inhp == *wp && *wp != '\0') - { - ++inhp; - ++wp; - } - - if (*wp == '\0' && (*inhp == '\0' || *inhp == ':')) - { - /* This object is on the list of objects for which the - RUNPATH and RPATH must not be used. */ - sps->dirs = (void *) -1; - return false; - } - - while (*inhp != '\0') - if (*inhp++ == ':') - break; - } - while (*inhp != '\0'); - } - - /* Make a writable copy. */ - copy = __strdup (rpath); - if (copy == NULL) - { - errstring = N_("cannot create RUNPATH/RPATH copy"); - goto signal_error; - } - - /* Ignore empty rpaths. */ - if (*copy == 0) - { - free (copy); - sps->dirs = (struct r_search_path_elem **) -1; - return false; - } - - /* Count the number of necessary elements in the result array. */ - nelems = 0; - for (cp = copy; *cp != '\0'; ++cp) - if (*cp == ':') - ++nelems; - - /* Allocate room for the result. NELEMS + 1 is an upper limit for the - number of necessary entries. */ - result = (struct r_search_path_elem **) malloc ((nelems + 1 + 1) - * sizeof (*result)); - if (result == NULL) - { - free (copy); - errstring = N_("cannot create cache for search path"); - signal_error: - _dl_signal_error (ENOMEM, NULL, NULL, errstring); - } - - fillin_rpath (copy, result, ":", 0, what, where, l); - - /* Free the copied RPATH string. `fillin_rpath' make own copies if - necessary. */ - free (copy); - - sps->dirs = result; - /* The caller will change this value if we haven't used a real malloc. */ - sps->malloced = 1; - return true; -} - -/* Make sure cached path information is stored in *SP - and return true if there are any paths to search there. */ -static bool -cache_rpath (struct link_map *l, - struct r_search_path_struct *sp, - int tag, - const char *what) -{ - if (sp->dirs == (void *) -1) - return false; - - if (sp->dirs != NULL) - return true; - - if (l->l_info[tag] == NULL) - { - /* There is no path. */ - sp->dirs = (void *) -1; - return false; - } - - /* Make sure the cache information is available. */ - return decompose_rpath (sp, (const char *) (D_PTR (l, l_info[DT_STRTAB]) - + l->l_info[tag]->d_un.d_val), - l, what); -} - - -void -internal_function -_dl_init_paths (const char *llp) -{ - size_t idx; - const char *strp; - struct r_search_path_elem *pelem, **aelem; - size_t round_size; - struct link_map __attribute__ ((unused)) *l = NULL; - /* Initialize to please the compiler. */ - const char *errstring = NULL; - - /* Fill in the information about the application's RPATH and the - directories addressed by the LD_LIBRARY_PATH environment variable. */ - - /* Get the capabilities. */ - capstr = _dl_important_hwcaps (GLRO(dl_platform), GLRO(dl_platformlen), - &ncapstr, &max_capstrlen); - - /* First set up the rest of the default search directory entries. */ - aelem = rtld_search_dirs.dirs = (struct r_search_path_elem **) - malloc ((nsystem_dirs_len + 1) * sizeof (struct r_search_path_elem *)); - if (rtld_search_dirs.dirs == NULL) - { - errstring = N_("cannot create search path array"); - signal_error: - _dl_signal_error (ENOMEM, NULL, NULL, errstring); - } - - round_size = ((2 * sizeof (struct r_search_path_elem) - 1 - + ncapstr * sizeof (enum r_dir_status)) - / sizeof (struct r_search_path_elem)); - - rtld_search_dirs.dirs[0] = (struct r_search_path_elem *) - malloc ((sizeof (system_dirs) / sizeof (system_dirs[0])) - * round_size * sizeof (struct r_search_path_elem)); - if (rtld_search_dirs.dirs[0] == NULL) - { - errstring = N_("cannot create cache for search path"); - goto signal_error; - } - - rtld_search_dirs.malloced = 0; - pelem = GL(dl_all_dirs) = rtld_search_dirs.dirs[0]; - strp = system_dirs; - idx = 0; - - do - { - size_t cnt; - - *aelem++ = pelem; - - pelem->what = "system search path"; - pelem->where = NULL; - - pelem->dirname = strp; - pelem->dirnamelen = system_dirs_len[idx]; - strp += system_dirs_len[idx] + 1; - - /* System paths must be absolute. */ - assert (pelem->dirname[0] == '/'); - for (cnt = 0; cnt < ncapstr; ++cnt) - pelem->status[cnt] = unknown; - - pelem->next = (++idx == nsystem_dirs_len ? NULL : (pelem + round_size)); - - pelem += round_size; - } - while (idx < nsystem_dirs_len); - - max_dirnamelen = SYSTEM_DIRS_MAX_LEN; - *aelem = NULL; - -#ifdef SHARED - /* This points to the map of the main object. */ - l = GL(dl_ns)[LM_ID_BASE]._ns_loaded; - if (l != NULL) - { - assert (l->l_type != lt_loaded); - - if (l->l_info[DT_RUNPATH]) - { - /* Allocate room for the search path and fill in information - from RUNPATH. */ - decompose_rpath (&l->l_runpath_dirs, - (const void *) (D_PTR (l, l_info[DT_STRTAB]) - + l->l_info[DT_RUNPATH]->d_un.d_val), - l, "RUNPATH"); - /* During rtld init the memory is allocated by the stub malloc, - prevent any attempt to free it by the normal malloc. */ - l->l_runpath_dirs.malloced = 0; - - /* The RPATH is ignored. */ - l->l_rpath_dirs.dirs = (void *) -1; - } - else - { - l->l_runpath_dirs.dirs = (void *) -1; - - if (l->l_info[DT_RPATH]) - { - /* Allocate room for the search path and fill in information - from RPATH. */ - decompose_rpath (&l->l_rpath_dirs, - (const void *) (D_PTR (l, l_info[DT_STRTAB]) - + l->l_info[DT_RPATH]->d_un.d_val), - l, "RPATH"); - /* During rtld init the memory is allocated by the stub - malloc, prevent any attempt to free it by the normal - malloc. */ - l->l_rpath_dirs.malloced = 0; - } - else - l->l_rpath_dirs.dirs = (void *) -1; - } - } -#endif /* SHARED */ - - if (llp != NULL && *llp != '\0') - { - size_t nllp; - const char *cp = llp; - char *llp_tmp; - -#ifdef SHARED - /* Expand DSTs. */ - size_t cnt = DL_DST_COUNT (llp, 1); - if (__glibc_likely (cnt == 0)) - llp_tmp = strdupa (llp); - else - { - /* Determine the length of the substituted string. */ - size_t total = DL_DST_REQUIRED (l, llp, strlen (llp), cnt); - - /* Allocate the necessary memory. */ - llp_tmp = (char *) alloca (total + 1); - llp_tmp = _dl_dst_substitute (l, llp, llp_tmp, 1); - } -#else - llp_tmp = strdupa (llp); -#endif - - /* Decompose the LD_LIBRARY_PATH contents. First determine how many - elements it has. */ - nllp = 1; - while (*cp) - { - if (*cp == ':' || *cp == ';') - ++nllp; - ++cp; - } - - env_path_list.dirs = (struct r_search_path_elem **) - malloc ((nllp + 1) * sizeof (struct r_search_path_elem *)); - if (env_path_list.dirs == NULL) - { - errstring = N_("cannot create cache for search path"); - goto signal_error; - } - - (void) fillin_rpath (llp_tmp, env_path_list.dirs, ":;", - __libc_enable_secure, "LD_LIBRARY_PATH", - NULL, l); - - if (env_path_list.dirs[0] == NULL) - { - free (env_path_list.dirs); - env_path_list.dirs = (void *) -1; - } - - env_path_list.malloced = 0; - } - else - env_path_list.dirs = (void *) -1; -} - - -static void -__attribute__ ((noreturn, noinline)) -lose (int code, int fd, const char *name, char *realname, struct link_map *l, - const char *msg, struct r_debug *r, Lmid_t nsid) -{ - /* The file might already be closed. */ - if (fd != -1) - (void) __close (fd); - if (l != NULL && l->l_origin != (char *) -1l) - free ((char *) l->l_origin); - free (l); - free (realname); - - if (r != NULL) - { - r->r_state = RT_CONSISTENT; - _dl_debug_state (); - LIBC_PROBE (map_failed, 2, nsid, r); - } - - _dl_signal_error (code, name, NULL, msg); -} - - -/* Map in the shared object NAME, actually located in REALNAME, and already - opened on FD. */ - -#ifndef EXTERNAL_MAP_FROM_FD -static -#endif -struct link_map * -_dl_map_object_from_fd (const char *name, const char *origname, int fd, - struct filebuf *fbp, char *realname, - struct link_map *loader, int l_type, int mode, - void **stack_endp, Lmid_t nsid) -{ - struct link_map *l = NULL; - const ElfW(Ehdr) *header; - const ElfW(Phdr) *phdr; - const ElfW(Phdr) *ph; - size_t maplength; - int type; - /* Initialize to keep the compiler happy. */ - const char *errstring = NULL; - int errval = 0; - struct r_debug *r = _dl_debug_initialize (0, nsid); - bool make_consistent = false; - - /* Get file information. */ - struct r_file_id id; - if (__glibc_unlikely (!_dl_get_file_id (fd, &id))) - { - errstring = N_("cannot stat shared object"); - call_lose_errno: - errval = errno; - call_lose: - lose (errval, fd, name, realname, l, errstring, - make_consistent ? r : NULL, nsid); - } - - /* Look again to see if the real name matched another already loaded. */ - 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. */ - __close (fd); - - /* If the name is not in the list of names for this object add - it. */ - free (realname); - add_name_to_object (l, name); - - return l; - } - -#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 (__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 - the real one for almost everything. */ - l = _dl_new_object (realname, name, l_type, loader, mode, nsid); - if (l == NULL) - goto fail_new; - - /* Refer to the real descriptor. */ - l->l_real = &GL(dl_rtld_map); - - /* No need to bump the refcount of the real object, ld.so will - never be unloaded. */ - __close (fd); - - /* Add the map for the mirrored object to the object list. */ - _dl_add_to_namespace_list (l, nsid); - - return l; - } -#endif - - if (mode & RTLD_NOLOAD) - { - /* We are not supposed to load the object unless it is already - loaded. So return now. */ - free (realname); - __close (fd); - return NULL; - } - - /* Print debugging message. */ - 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'. */ - header = (void *) fbp->buf; - -#ifndef MAP_ANON -# define MAP_ANON 0 - if (_dl_zerofd == -1) - { - _dl_zerofd = _dl_sysdep_open_zero_fill (); - if (_dl_zerofd == -1) - { - free (realname); - __close (fd); - _dl_signal_error (errno, NULL, NULL, - N_("cannot open zero fill device")); - } - } -#endif - - /* Signal that we are going to add new objects. */ - if (r->r_state == RT_CONSISTENT) - { -#ifdef SHARED - /* Auditing checkpoint: we are going to add new objects. */ - if ((mode & __RTLD_AUDIT) == 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. */ - if (head->l_auditing == 0) - { - struct audit_ifaces *afct = GLRO(dl_audit); - for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) - { - if (afct->activity != NULL) - afct->activity (&head->l_audit[cnt].cookie, LA_ACT_ADD); - - afct = afct->next; - } - } - } -#endif - - /* Notify the debugger we have added some objects. We need to - call _dl_debug_initialize in a static program in case dynamic - linking has not been used before. */ - r->r_state = RT_ADD; - _dl_debug_state (); - LIBC_PROBE (map_start, 2, nsid, r); - make_consistent = true; - } - else - assert (r->r_state == RT_ADD); - - /* Enter the new object in the list of loaded objects. */ - l = _dl_new_object (realname, name, l_type, loader, mode, nsid); - if (__glibc_unlikely (l == NULL)) - { -#ifdef SHARED - fail_new: -#endif - errstring = N_("cannot create shared object descriptor"); - goto call_lose_errno; - } - - /* Extract the remaining details we need from the ELF header - and then read in the program header table. */ - l->l_entry = header->e_entry; - type = header->e_type; - l->l_phnum = header->e_phnum; - - maplength = header->e_phnum * sizeof (ElfW(Phdr)); - if (header->e_phoff + maplength <= (size_t) fbp->len) - phdr = (void *) (fbp->buf + header->e_phoff); - else - { - phdr = alloca (maplength); - __lseek (fd, header->e_phoff, SEEK_SET); - if ((size_t) __libc_read (fd, (void *) phdr, maplength) != maplength) - { - errstring = N_("cannot read file data"); - goto call_lose_errno; - } - } - - /* On most platforms presume that PT_GNU_STACK is absent and the stack is - * executable. Other platforms default to a nonexecutable stack and don't - * need PT_GNU_STACK to do so. */ - uint_fast16_t stack_flags = DEFAULT_STACK_PERMS; - - { - /* Scan the program header table, collecting its load commands. */ - struct loadcmd loadcmds[l->l_phnum]; - size_t nloadcmds = 0; - bool has_holes = false; - - /* The struct is initialized to zero so this is not necessary: - l->l_ld = 0; - l->l_phdr = 0; - l->l_addr = 0; */ - for (ph = phdr; ph < &phdr[l->l_phnum]; ++ph) - switch (ph->p_type) - { - /* These entries tell us where to find things once the file's - segments are mapped in. We record the addresses it says - verbatim, and later correct for the run-time load address. */ - case PT_DYNAMIC: - l->l_ld = (void *) ph->p_vaddr; - l->l_ldnum = ph->p_memsz / sizeof (ElfW(Dyn)); - break; - - case PT_PHDR: - l->l_phdr = (void *) ph->p_vaddr; - break; - - 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 (__glibc_unlikely ((ph->p_align & (GLRO(dl_pagesize) - 1)) != 0)) - { - errstring = N_("ELF load command alignment not page-aligned"); - goto call_lose; - } - 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; - } - - struct loadcmd *c = &loadcmds[nloadcmds++]; - c->mapstart = ALIGN_DOWN (ph->p_vaddr, GLRO(dl_pagesize)); - c->mapend = ALIGN_UP (ph->p_vaddr + ph->p_filesz, GLRO(dl_pagesize)); - c->dataend = ph->p_vaddr + ph->p_filesz; - c->allocend = ph->p_vaddr + ph->p_memsz; - c->mapoff = ALIGN_DOWN (ph->p_offset, GLRO(dl_pagesize)); - - /* Determine whether there is a gap between the last segment - and this one. */ - if (nloadcmds > 1 && c[-1].mapend != c->mapstart) - has_holes = true; - - /* Optimize a common case. */ -#if (PF_R | PF_W | PF_X) == 7 && (PROT_READ | PROT_WRITE | PROT_EXEC) == 7 - c->prot = (PF_TO_PROT - >> ((ph->p_flags & (PF_R | PF_W | PF_X)) * 4)) & 0xf; -#else - c->prot = 0; - if (ph->p_flags & PF_R) - c->prot |= PROT_READ; - if (ph->p_flags & PF_W) - c->prot |= PROT_WRITE; - if (ph->p_flags & PF_X) - c->prot |= PROT_EXEC; -#endif - break; - - case PT_TLS: - if (ph->p_memsz == 0) - /* Nothing to do for an empty segment. */ - break; - - l->l_tls_blocksize = ph->p_memsz; - l->l_tls_align = ph->p_align; - if (ph->p_align == 0) - l->l_tls_firstbyte_offset = 0; - else - l->l_tls_firstbyte_offset = ph->p_vaddr & (ph->p_align - 1); - l->l_tls_initimage_size = ph->p_filesz; - /* Since we don't know the load address yet only store the - offset. We will adjust it later. */ - l->l_tls_initimage = (void *) ph->p_vaddr; - - /* If not loading the initial set of shared libraries, - check whether we should permit loading a TLS segment. */ - 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. */ - || __glibc_likely (GL(dl_tls_dtv_slotinfo_list) != NULL)) - { - /* Assign the next available module ID. */ - l->l_tls_modid = _dl_next_tls_modid (); - break; - } - -#ifdef SHARED - /* We are loading the executable itself when the dynamic - linker was executed directly. The setup will happen - later. Otherwise, the TLS data structures are already - initialized, and we assigned a TLS modid above. */ - assert (l->l_prev == NULL || (mode & __RTLD_AUDIT) != 0); -#else - assert (false && "TLS not initialized in static application"); -#endif - break; - - case PT_GNU_STACK: - stack_flags = ph->p_flags; - break; - - case PT_GNU_RELRO: - l->l_relro_addr = ph->p_vaddr; - l->l_relro_size = ph->p_memsz; - break; - } - - 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 - calculations below using NLOADCMDS - 1. */ - errstring = N_("object file has no loadable segments"); - goto call_lose; - } - - 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; - } - - /* 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 (__glibc_unlikely (type == ET_DYN)) - { - errstring = N_("object file has no dynamic section"); - goto call_lose; - } - } - else - l->l_ld = (ElfW(Dyn) *) ((ElfW(Addr)) l->l_ld + l->l_addr); - - elf_get_dynamic_info (l, NULL); - - /* Make sure we are not dlopen'ing an object that has the - DF_1_NOOPEN flag set. */ - if (__glibc_unlikely (l->l_flags_1 & DF_1_NOOPEN) - && (mode & __RTLD_DLOPEN)) - { - /* We are not supposed to load this object. Free all resources. */ - _dl_unmap_segments (l); - - if (!l->l_libname->dont_free) - free (l->l_libname); - - if (l->l_phdr_allocated) - free ((void *) l->l_phdr); - - errstring = N_("shared object cannot be dlopen()ed"); - goto call_lose; - } - - if (l->l_phdr == NULL) - { - /* The program header is not contained in any of the segments. - We have to allocate memory ourself and copy it over from out - temporary place. */ - ElfW(Phdr) *newp = (ElfW(Phdr) *) malloc (header->e_phnum - * sizeof (ElfW(Phdr))); - if (newp == NULL) - { - errstring = N_("cannot allocate memory for program header"); - goto call_lose_errno; - } - - l->l_phdr = memcpy (newp, phdr, - (header->e_phnum * sizeof (ElfW(Phdr)))); - l->l_phdr_allocated = 1; - } - else - /* Adjust the PT_PHDR value by the runtime load address. */ - l->l_phdr = (ElfW(Phdr) *) ((ElfW(Addr)) l->l_phdr + l->l_addr); - - if (__glibc_unlikely ((stack_flags &~ GL(dl_stack_flags)) & PF_X)) - { - if (__glibc_unlikely (__check_caller (RETURN_ADDRESS (0), allow_ldso) != 0)) - { - errstring = N_("invalid caller"); - goto call_lose; - } - - /* The stack is presently not executable, but this module - requires that it be executable. We must change the - protection of the variable which contains the flags used in - the mprotect calls. */ -#ifdef SHARED - if ((mode & (__RTLD_DLOPEN | __RTLD_AUDIT)) == __RTLD_DLOPEN) - { - const uintptr_t p = (uintptr_t) &__stack_prot & -GLRO(dl_pagesize); - const size_t s = (uintptr_t) (&__stack_prot + 1) - p; - - struct link_map *const m = &GL(dl_rtld_map); - const uintptr_t relro_end = ((m->l_addr + m->l_relro_addr - + m->l_relro_size) - & -GLRO(dl_pagesize)); - 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) - { - errstring = N_("cannot change memory protections"); - goto call_lose_errno; - } - __stack_prot |= PROT_READ|PROT_WRITE|PROT_EXEC; - __mprotect ((void *) p, s, PROT_READ); - } - else - __stack_prot |= PROT_READ|PROT_WRITE|PROT_EXEC; - } - else -#endif - __stack_prot |= PROT_READ|PROT_WRITE|PROT_EXEC; - -#ifdef check_consistency - check_consistency (); -#endif - - errval = (*GL(dl_make_stack_executable_hook)) (stack_endp); - if (errval) - { - errstring = N_("\ -cannot enable executable stack as shared object requires"); - goto call_lose; - } - } - - /* Adjust the address of the TLS initialization image. */ - if (l->l_tls_initimage != NULL) - 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 (__glibc_unlikely (__close (fd) != 0)) - { - errstring = N_("cannot close file descriptor"); - goto call_lose_errno; - } - /* Signal that we closed the file. */ - fd = -1; - - /* 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 (__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", - (int) sizeof (void *) * 2, - (unsigned long int) l->l_ld, - (int) sizeof (void *) * 2, - (unsigned long int) l->l_addr, - (int) sizeof (void *) * 2, maplength, - (int) sizeof (void *) * 2, - (unsigned long int) l->l_entry, - (int) sizeof (void *) * 2, - (unsigned long int) l->l_phdr, - (int) sizeof (void *) * 2, l->l_phnum); - - /* Set up the symbol hash table. */ - _dl_setup_hash (l); - - /* 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 - && __glibc_unlikely (l->l_info[DT_SYMBOLIC] != NULL) - && &l->l_searchlist != l->l_scope[0]) - { - /* Create an appropriate searchlist. It contains only this map. - This is the definition of DT_SYMBOLIC in SysVr4. */ - l->l_symbolic_searchlist.r_list[0] = l; - l->l_symbolic_searchlist.r_nlist = 1; - - /* Now move the existing entries one back. */ - memmove (&l->l_scope[1], &l->l_scope[0], - (l->l_scope_max - 1) * sizeof (l->l_scope[0])); - - /* Now add the new entry. */ - l->l_scope[0] = &l->l_symbolic_searchlist; - } - - /* Remember whether this object must be initialized first. */ - if (l->l_flags_1 & DF_1_INITFIRST) - GL(dl_initfirst) = l; - - /* Finally the file information. */ - l->l_file_id = id; - -#ifdef SHARED - /* When auditing is used the recorded names might not include the - name by which the DSO is actually known. Add that as well. */ - if (__glibc_unlikely (origname != NULL)) - add_name_to_object (l, origname); -#else - /* Audit modules only exist when linking is dynamic so ORIGNAME - cannot be non-NULL. */ - assert (origname == NULL); -#endif - - /* When we profile the SONAME might be needed for something else but - loading. Add it right away. */ - 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)); - -#ifdef DL_AFTER_LOAD - DL_AFTER_LOAD (l); -#endif - - /* Now that the object is fully initialized add it to the object list. */ - _dl_add_to_namespace_list (l, nsid); - -#ifdef SHARED - /* Auditing checkpoint: we have a new object. */ - if (__glibc_unlikely (GLRO(dl_naudit) > 0) - && !GL(dl_ns)[l->l_ns]._ns_loaded->l_auditing) - { - struct audit_ifaces *afct = GLRO(dl_audit); - for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) - { - if (afct->objopen != NULL) - { - l->l_audit[cnt].bindflags - = afct->objopen (l, nsid, &l->l_audit[cnt].cookie); - - l->l_audit_any_plt |= l->l_audit[cnt].bindflags != 0; - } - - afct = afct->next; - } - } -#endif - - return l; -} - -/* Print search path. */ -static void -print_search_path (struct r_search_path_elem **list, - const char *what, const char *name) -{ - char buf[max_dirnamelen + max_capstrlen]; - int first = 1; - - _dl_debug_printf (" search path="); - - while (*list != NULL && (*list)->what == what) /* Yes, ==. */ - { - char *endp = __mempcpy (buf, (*list)->dirname, (*list)->dirnamelen); - size_t cnt; - - for (cnt = 0; cnt < ncapstr; ++cnt) - if ((*list)->status[cnt] != nonexisting) - { - char *cp = __mempcpy (endp, capstr[cnt].str, capstr[cnt].len); - if (cp == buf || (cp == buf + 1 && buf[0] == '/')) - cp[0] = '\0'; - else - cp[-1] = '\0'; - - _dl_debug_printf_c (first ? "%s" : ":%s", buf); - first = 0; - } - - ++list; - } - - if (name != NULL) - _dl_debug_printf_c ("\t\t(%s from file %s)\n", what, - DSO_FILENAME (name)); - else - _dl_debug_printf_c ("\t\t(%s)\n", what); -} - -/* Open a file and verify it is an ELF file for this architecture. We - ignore only ELF files for other architectures. Non-ELF files and - ELF files with different header information cause fatal errors since - this could mean there is something wrong in the installation and the - user might want to know about this. - - If FD is not -1, then the file is already open and FD refers to it. - In that case, FD is consumed for both successful and error returns. */ -static int -open_verify (const char *name, int fd, - struct filebuf *fbp, struct link_map *loader, - int whatcode, int mode, bool *found_other_class, bool free_name) -{ - /* This is the expected ELF header. */ -#define ELF32_CLASS ELFCLASS32 -#define ELF64_CLASS ELFCLASS64 -#ifndef VALID_ELF_HEADER -# define VALID_ELF_HEADER(hdr,exp,size) (memcmp (hdr, exp, size) == 0) -# define VALID_ELF_OSABI(osabi) (osabi == ELFOSABI_SYSV) -# define VALID_ELF_ABIVERSION(osabi,ver) (ver == 0) -#elif defined MORE_ELF_HEADER_DATA - MORE_ELF_HEADER_DATA; -#endif - static const unsigned char expected[EI_NIDENT] = - { - [EI_MAG0] = ELFMAG0, - [EI_MAG1] = ELFMAG1, - [EI_MAG2] = ELFMAG2, - [EI_MAG3] = ELFMAG3, - [EI_CLASS] = ELFW(CLASS), - [EI_DATA] = byteorder, - [EI_VERSION] = EV_CURRENT, - [EI_OSABI] = ELFOSABI_SYSV, - [EI_ABIVERSION] = 0 - }; - static const struct - { - ElfW(Word) vendorlen; - ElfW(Word) datalen; - ElfW(Word) type; - char vendor[4]; - } expected_note = { 4, 16, 1, "GNU" }; - /* Initialize it to make the compiler happy. */ - const char *errstring = NULL; - int errval = 0; - -#ifdef SHARED - /* Give the auditing libraries a chance. */ - if (__glibc_unlikely (GLRO(dl_naudit) > 0) && whatcode != 0 - && loader->l_auditing == 0) - { - const char *original_name = name; - struct audit_ifaces *afct = GLRO(dl_audit); - for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) - { - if (afct->objsearch != NULL) - { - name = afct->objsearch (name, &loader->l_audit[cnt].cookie, - whatcode); - if (name == NULL) - /* Ignore the path. */ - return -1; - } - - afct = afct->next; - } - - if (fd != -1 && name != original_name && strcmp (name, original_name)) - { - /* An audit library changed what we're supposed to open, - so FD no longer matches it. */ - __close (fd); - fd = -1; - } - } -#endif - - if (fd == -1) - /* Open the file. We always open files read-only. */ - fd = __open (name, O_RDONLY | O_CLOEXEC); - - if (fd != -1) - { - ElfW(Ehdr) *ehdr; - ElfW(Phdr) *phdr, *ph; - ElfW(Word) *abi_note; - unsigned int osversion; - size_t maplength; - - /* We successfully opened the file. Now verify it is a file - we can use. */ - __set_errno (0); - fbp->len = 0; - assert (sizeof (fbp->buf) > sizeof (ElfW(Ehdr))); - /* Read in the header. */ - do - { - ssize_t retlen = __libc_read (fd, fbp->buf + fbp->len, - sizeof (fbp->buf) - fbp->len); - if (retlen <= 0) - break; - fbp->len += retlen; - } - 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 (__glibc_unlikely (fbp->len < (ssize_t) sizeof (ElfW(Ehdr)))) - { - errval = errno; - errstring = (errval == 0 - ? N_("file too short") : N_("cannot read file data")); - call_lose: - if (free_name) - { - char *realname = (char *) name; - name = strdupa (realname); - free (realname); - } - lose (errval, fd, name, NULL, NULL, errstring, NULL, 0); - } - - /* See whether the ELF header is what we expect. */ - 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)) - { - /* Something is wrong. */ - const Elf32_Word *magp = (const void *) ehdr->e_ident; - if (*magp != -#if BYTE_ORDER == LITTLE_ENDIAN - ((ELFMAG0 << (EI_MAG0 * 8)) | - (ELFMAG1 << (EI_MAG1 * 8)) | - (ELFMAG2 << (EI_MAG2 * 8)) | - (ELFMAG3 << (EI_MAG3 * 8))) -#else - ((ELFMAG0 << (EI_MAG3 * 8)) | - (ELFMAG1 << (EI_MAG2 * 8)) | - (ELFMAG2 << (EI_MAG1 * 8)) | - (ELFMAG3 << (EI_MAG0 * 8))) -#endif - ) - errstring = N_("invalid ELF header"); - else if (ehdr->e_ident[EI_CLASS] != ELFW(CLASS)) - { - /* This is not a fatal error. On architectures where - 32-bit and 64-bit binaries can be run this might - happen. */ - *found_other_class = true; - goto close_and_out; - } - else if (ehdr->e_ident[EI_DATA] != byteorder) - { - if (BYTE_ORDER == BIG_ENDIAN) - errstring = N_("ELF file data encoding not big-endian"); - else - errstring = N_("ELF file data encoding not little-endian"); - } - else if (ehdr->e_ident[EI_VERSION] != EV_CURRENT) - errstring - = N_("ELF file version ident does not match current one"); - /* XXX We should be able so set system specific versions which are - allowed here. */ - else if (!VALID_ELF_OSABI (ehdr->e_ident[EI_OSABI])) - errstring = N_("ELF file OS ABI invalid"); - else if (!VALID_ELF_ABIVERSION (ehdr->e_ident[EI_OSABI], - ehdr->e_ident[EI_ABIVERSION])) - errstring = N_("ELF file ABI version invalid"); - else if (memcmp (&ehdr->e_ident[EI_PAD], &expected[EI_PAD], - EI_NIDENT - EI_PAD) != 0) - errstring = N_("nonzero padding in e_ident"); - else - /* Otherwise we don't know what went wrong. */ - errstring = N_("internal error"); - - goto call_lose; - } - - if (__glibc_unlikely (ehdr->e_version != EV_CURRENT)) - { - errstring = N_("ELF file version does not match current one"); - goto call_lose; - } - if (! __glibc_likely (elf_machine_matches_host (ehdr))) - goto close_and_out; - 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 (__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; - } - - maplength = ehdr->e_phnum * sizeof (ElfW(Phdr)); - if (ehdr->e_phoff + maplength <= (size_t) fbp->len) - phdr = (void *) (fbp->buf + ehdr->e_phoff); - else - { - phdr = alloca (maplength); - __lseek (fd, ehdr->e_phoff, SEEK_SET); - if ((size_t) __libc_read (fd, (void *) phdr, maplength) != maplength) - { - read_error: - errval = errno; - errstring = N_("cannot read file data"); - goto call_lose; - } - } - - 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) - { - ElfW(Addr) size = ph->p_filesz; - - if (ph->p_offset + size <= (size_t) fbp->len) - abi_note = (void *) (fbp->buf + ph->p_offset); - else - { - abi_note = alloca (size); - __lseek (fd, ph->p_offset, SEEK_SET); - if (__libc_read (fd, (void *) abi_note, size) != size) - goto read_error; - } - - while (memcmp (abi_note, &expected_note, sizeof (expected_note))) - { -#define ROUND(len) (((len) + sizeof (ElfW(Word)) - 1) & -sizeof (ElfW(Word))) - ElfW(Addr) note_size = 3 * sizeof (ElfW(Word)) - + ROUND (abi_note[0]) - + ROUND (abi_note[1]); - - if (size - 32 < note_size) - { - size = 0; - break; - } - size -= note_size; - abi_note = (void *) abi_note + note_size; - } - - if (size == 0) - continue; - - osversion = (abi_note[5] & 0xff) * 65536 - + (abi_note[6] & 0xff) * 256 - + (abi_note[7] & 0xff); - if (abi_note[4] != __ABI_TAG_OS - || (GLRO(dl_osversion) && GLRO(dl_osversion) < osversion)) - { - close_and_out: - __close (fd); - __set_errno (ENOENT); - fd = -1; - } - - break; - } - } - - return fd; -} - -/* Try to open NAME in one of the directories in *DIRSP. - Return the fd, or -1. If successful, fill in *REALNAME - with the malloc'd full directory name. If it turns out - that none of the directories in *DIRSP exists, *DIRSP is - replaced with (void *) -1, and the old value is free()d - if MAY_FREE_DIRS is true. */ - -static int -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) -{ - struct r_search_path_elem **dirs = sps->dirs; - char *buf; - int fd = -1; - const char *current_what = NULL; - int any = 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; - - buf = alloca (max_dirnamelen + max_capstrlen + namelen); - do - { - struct r_search_path_elem *this_dir = *dirs; - size_t buflen = 0; - size_t cnt; - char *edp; - int here_any = 0; - int err; - - /* If we are debugging the search for libraries print the path - now if it hasn't happened now. */ - if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_LIBS) - && current_what != this_dir->what) - { - current_what = this_dir->what; - print_search_path (dirs, current_what, this_dir->where); - } - - edp = (char *) __mempcpy (buf, this_dir->dirname, this_dir->dirnamelen); - for (cnt = 0; fd == -1 && cnt < ncapstr; ++cnt) - { - /* Skip this directory if we know it does not exist. */ - if (this_dir->status[cnt] == nonexisting) - continue; - - buflen = - ((char *) __mempcpy (__mempcpy (edp, capstr[cnt].str, - capstr[cnt].len), - name, namelen) - - buf); - - /* Print name we try if this is wanted. */ - if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_LIBS)) - _dl_debug_printf (" trying file=%s\n", buf); - - fd = open_verify (buf, -1, fbp, loader, whatcode, mode, - found_other_class, false); - if (this_dir->status[cnt] == unknown) - { - if (fd != -1) - this_dir->status[cnt] = existing; - /* Do not update the directory information when loading - auditing code. We must try to disturb the program as - little as possible. */ - else if (loader == NULL - || GL(dl_ns)[loader->l_ns]._ns_loaded->l_auditing == 0) - { - /* We failed to open machine dependent library. Let's - test whether there is any directory at all. */ - struct stat64 st; - - buf[buflen - namelen - 1] = '\0'; - - if (__xstat64 (_STAT_VER, buf, &st) != 0 - || ! S_ISDIR (st.st_mode)) - /* The directory does not exist or it is no directory. */ - this_dir->status[cnt] = nonexisting; - else - this_dir->status[cnt] = existing; - } - } - - /* Remember whether we found any existing directory. */ - here_any |= this_dir->status[cnt] != nonexisting; - - 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 - directories and so exploit the bugs. */ - struct stat64 st; - - if (__fxstat64 (_STAT_VER, fd, &st) != 0 - || (st.st_mode & S_ISUID) == 0) - { - /* The shared object cannot be tested for being SUID - or this bit is not set. In this case we must not - use this object. */ - __close (fd); - fd = -1; - /* We simply ignore the file, signal this by setting - the error value which would have been set by `open'. */ - errno = ENOENT; - } - } - } - - if (fd != -1) - { - *realname = (char *) malloc (buflen); - if (*realname != NULL) - { - memcpy (*realname, buf, buflen); - return fd; - } - else - { - /* No memory for the name, we certainly won't be able - to load and link it. */ - __close (fd); - return -1; - } - } - if (here_any && (err = errno) != ENOENT && err != EACCES) - /* The file exists and is readable, but something went wrong. */ - return -1; - - /* Remember whether we found anything. */ - any |= here_any; - } - while (*++dirs != NULL); - - /* Remove the whole path if none of the directories exists. */ - 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 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; - } - - return -1; -} - -/* Map in the shared object file NAME. */ - -struct link_map * -internal_function -_dl_map_object (struct link_map *loader, const char *name, - int type, int trace_mode, int mode, Lmid_t nsid) -{ - int fd; - const char *origname = NULL; - char *realname; - char *name_copy; - struct link_map *l; - struct filebuf fb; - - assert (nsid >= 0); - assert (nsid < GL(dl_nns)); - - /* Look for this name among those already loaded. */ - for (l = GL(dl_ns)[nsid]._ns_loaded; l; l = l->l_next) - { - /* If 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 (__glibc_unlikely ((l->l_faked | l->l_removed) != 0)) - continue; - if (!_dl_name_match_p (name, l)) - { - const char *soname; - - if (__glibc_likely (l->l_soname_added) - || l->l_info[DT_SONAME] == NULL) - continue; - - soname = ((const char *) D_PTR (l, l_info[DT_STRTAB]) - + l->l_info[DT_SONAME]->d_un.d_val); - if (strcmp (name, soname) != 0) - continue; - - /* We have a match on a new name -- cache it. */ - add_name_to_object (l, soname); - l->l_soname_added = 1; - } - - /* We have a match. */ - return l; - } - - /* Display information if we are debugging. */ - 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" - : "\nfile=%s [%lu]; dynamically loaded by %s [%lu]\n", - name, nsid, DSO_FILENAME (loader->l_name), loader->l_ns); - -#ifdef SHARED - /* Give the auditing libraries a chance to change the name before we - try anything. */ - if (__glibc_unlikely (GLRO(dl_naudit) > 0) - && (loader == NULL || loader->l_auditing == 0)) - { - struct audit_ifaces *afct = GLRO(dl_audit); - for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) - { - if (afct->objsearch != NULL) - { - const char *before = name; - name = afct->objsearch (name, &loader->l_audit[cnt].cookie, - LA_SER_ORIG); - if (name == NULL) - { - /* Do not try anything further. */ - fd = -1; - goto no_file; - } - if (before != name && strcmp (before, name) != 0) - { - if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES)) - _dl_debug_printf ("audit changed filename %s -> %s\n", - before, name); - - if (origname == NULL) - origname = before; - } - } - - afct = afct->next; - } - } -#endif - - /* Will be true if we found a DSO which is of the other ELF class. */ - bool found_other_class = false; - - if (strchr (name, '/') == NULL) - { - /* Search for NAME in several places. */ - - size_t namelen = strlen (name) + 1; - - if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_LIBS)) - _dl_debug_printf ("find library=%s [%lu]; searching\n", name, nsid); - - fd = -1; - - /* When the object has the RUNPATH information we don't use any - RPATHs. */ - if (loader == NULL || loader->l_info[DT_RUNPATH] == NULL) - { - /* This is the executable's map (if there is one). Make sure that - we do not look at it twice. */ - struct link_map *main_map = GL(dl_ns)[LM_ID_BASE]._ns_loaded; - bool did_main_map = false; - - /* First try the DT_RPATH of the dependent object that caused NAME - to be loaded. Then that object's dependent, and on up. */ - 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, - &l->l_rpath_dirs, - &realname, &fb, loader, LA_SER_RUNPATH, - &found_other_class); - if (fd != -1) - break; - - did_main_map |= l == main_map; - } - - /* If dynamically linked, try the DT_RPATH of the executable - itself. NB: we do this for lookups in any namespace. */ - if (fd == -1 && !did_main_map - && 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, - &main_map->l_rpath_dirs, - &realname, &fb, loader ?: main_map, LA_SER_RUNPATH, - &found_other_class); - } - - /* Try the LD_LIBRARY_PATH environment variable. */ - if (fd == -1 && env_path_list.dirs != (void *) -1) - 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); - - /* Look at the RUNPATH information for this binary. */ - if (fd == -1 && loader != NULL - && cache_rpath (loader, &loader->l_runpath_dirs, - DT_RUNPATH, "RUNPATH")) - fd = open_path (name, namelen, mode, - &loader->l_runpath_dirs, &realname, &fb, loader, - LA_SER_RUNPATH, &found_other_class); - - if (fd == -1) - { - realname = _dl_sysdep_open_object (name, namelen, &fd); - if (realname != NULL) - { - fd = open_verify (realname, fd, - &fb, loader ?: GL(dl_ns)[nsid]._ns_loaded, - LA_SER_CONFIG, mode, &found_other_class, - false); - if (fd == -1) - free (realname); - } - } - -#ifdef USE_LDCONFIG - if (fd == -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. */ - char *cached = _dl_load_cache_lookup (name); - - if (cached != NULL) - { - // XXX Correct to unconditionally default to namespace 0? - l = (loader - ?: GL(dl_ns)[LM_ID_BASE]._ns_loaded -# ifdef SHARED - ?: &GL(dl_rtld_map) -# endif - ); - - /* If the loader has the DF_1_NODEFLIB flag set we must not - use a cache entry from any of these directories. */ - if (__glibc_unlikely (l->l_flags_1 & DF_1_NODEFLIB)) - { - const char *dirp = system_dirs; - unsigned int cnt = 0; - - do - { - if (memcmp (cached, dirp, system_dirs_len[cnt]) == 0) - { - /* The prefix matches. Don't use the entry. */ - free (cached); - cached = NULL; - break; - } - - dirp += system_dirs_len[cnt] + 1; - ++cnt; - } - while (cnt < nsystem_dirs_len); - } - - if (cached != NULL) - { - fd = open_verify (cached, -1, - &fb, loader ?: GL(dl_ns)[nsid]._ns_loaded, - LA_SER_CONFIG, mode, &found_other_class, - false); - if (__glibc_likely (fd != -1)) - realname = cached; - else - free (cached); - } - } - } -#endif - - /* Finally, try the default path. */ - if (fd == -1 - && ((l = loader ?: GL(dl_ns)[nsid]._ns_loaded) == NULL - || __glibc_likely (!(l->l_flags_1 & DF_1_NODEFLIB))) - && rtld_search_dirs.dirs != (void *) -1) - 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 (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_LIBS)) - _dl_debug_printf ("\n"); - } - else - { - /* The path may contain dynamic string tokens. */ - realname = (loader - ? expand_dynamic_string_token (loader, name, 0) - : __strdup (name)); - if (realname == NULL) - fd = -1; - else - { - fd = open_verify (realname, -1, &fb, - loader ?: GL(dl_ns)[nsid]._ns_loaded, 0, mode, - &found_other_class, true); - if (__glibc_unlikely (fd == -1)) - free (realname); - } - } - -#ifdef SHARED - no_file: -#endif - /* In case the LOADER information has only been provided to get to - the appropriate RUNPATH/RPATH information we do not need it - anymore. */ - if (mode & __RTLD_CALLMAP) - loader = NULL; - - if (__glibc_unlikely (fd == -1)) - { - if (trace_mode - && __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 - so severe. Fake an entry with all the information we - have. */ - static const Elf_Symndx dummy_bucket = STN_UNDEF; - - /* Allocate a new object map. */ - if ((name_copy = __strdup (name)) == NULL - || (l = _dl_new_object (name_copy, name, type, loader, - mode, nsid)) == NULL) - { - free (name_copy); - _dl_signal_error (ENOMEM, name, NULL, - N_("cannot create shared object descriptor")); - } - /* Signal that this is a faked entry. */ - l->l_faked = 1; - /* Since the descriptor is initialized with zero we do not - have do this here. - l->l_reserved = 0; */ - l->l_buckets = &dummy_bucket; - l->l_nbuckets = 1; - l->l_relocated = 1; - - /* Enter the object in the object list. */ - _dl_add_to_namespace_list (l, nsid); - - return l; - } - else if (found_other_class) - _dl_signal_error (0, name, NULL, - ELFW(CLASS) == ELFCLASS32 - ? N_("wrong ELF class: ELFCLASS64") - : N_("wrong ELF class: ELFCLASS32")); - else - _dl_signal_error (errno, name, NULL, - N_("cannot open shared object file")); - } - - void *stack_end = __libc_stack_end; - return _dl_map_object_from_fd (name, origname, fd, &fb, realname, loader, - type, mode, &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 -_dl_rtld_di_serinfo (struct link_map *loader, Dl_serinfo *si, bool counting) -{ - if (counting) - { - si->dls_cnt = 0; - si->dls_size = 0; - } - - struct add_path_state p = - { - .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) - { - /* First try the DT_RPATH of the dependent object that caused NAME - to be loaded. Then that object's dependent, and on up. */ - - struct link_map *l = loader; - do - { - if (cache_rpath (l, &l->l_rpath_dirs, DT_RPATH, "RPATH")) - add_path (&p, &l->l_rpath_dirs, XXX_RPATH); - l = l->l_loader; - } - while (l != NULL); - - /* If dynamically linked, try the DT_RPATH of the executable itself. */ - if (loader->l_ns == LM_ID_BASE) - { - 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 (&p, &l->l_rpath_dirs, XXX_RPATH); - } - } - - /* Try the LD_LIBRARY_PATH environment variable. */ - 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 (&p, &loader->l_runpath_dirs, XXX_RUNPATH); - - /* XXX - Here is where ld.so.cache gets checked, but we don't have - a way to indicate that in the results for Dl_serinfo. */ - - /* Finally, try the default path. */ - if (!(loader->l_flags_1 & DF_1_NODEFLIB)) - add_path (&p, &rtld_search_dirs, XXX_default); - - if (counting) - /* Count the struct size before the string area, which we didn't - know before we completed dls_cnt. */ - si->dls_size += (char *) &si->dls_serpath[si->dls_cnt] - (char *) si; -} diff --git a/elf/dl-load.h b/elf/dl-load.h deleted file mode 100644 index 7cd6214d4e..0000000000 --- a/elf/dl-load.h +++ /dev/null @@ -1,135 +0,0 @@ -/* Map in a shared object's segments from the file. - Copyright (C) 1995-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -#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 deleted file mode 100644 index 3d2369dbf2..0000000000 --- a/elf/dl-lookup.c +++ /dev/null @@ -1,1129 +0,0 @@ -/* Look up a symbol in the loaded objects. - Copyright (C) 1995-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -#include <alloca.h> -#include <libintl.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <ldsodefs.h> -#include <dl-hash.h> -#include <dl-machine.h> -#include <sysdep-cancel.h> -#include <libc-lock.h> -#include <tls.h> -#include <atomic.h> - -#include <assert.h> - -/* 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 - -#define VERSTAG(tag) (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGIDX (tag)) - - -struct sym_val - { - const ElfW(Sym) *s; - struct link_map *m; - }; - - -#define make_string(string, rest...) \ - ({ \ - const char *all[] = { string, ## rest }; \ - size_t len, cnt; \ - char *result, *cp; \ - \ - len = 1; \ - for (cnt = 0; cnt < sizeof (all) / sizeof (all[0]); ++cnt) \ - len += strlen (all[cnt]); \ - \ - cp = result = alloca (len); \ - for (cnt = 0; cnt < sizeof (all) / sizeof (all[0]); ++cnt) \ - cp = __stpcpy (cp, all[cnt]); \ - \ - result; \ - }) - -/* Statistics function. */ -#ifdef SHARED -# define bump_num_relocations() ++GL(dl_num_relocations) -#else -# 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 - something bad happened. */ -static int -__attribute_noinline__ -do_lookup_x (const char *undef_name, uint_fast32_t new_hash, - unsigned long int *old_hash, const ElfW(Sym) *ref, - struct sym_val *result, struct r_scope_elem *scope, size_t i, - const struct r_found_version *const version, int flags, - struct link_map *skip, int type_class, struct link_map *undef_map) -{ - size_t n = scope->r_nlist; - /* Make sure we read the value before proceeding. Otherwise we - might use r_list pointing to the initial scope and r_nlist being - the value after a resize. That is the only path in dl-open.c not - protected by GSCOPE. A read barrier here might be to expensive. */ - __asm volatile ("" : "+r" (n), "+m" (scope->r_list)); - struct link_map **list = scope->r_list; - - do - { - const struct link_map *map = list[i]->l_real; - - /* Here come the extra test needed for `_dl_lookup_symbol_skip'. */ - if (map == skip) - continue; - - /* Don't search the executable when resolving a copy reloc. */ - if ((type_class & ELF_RTYPE_CLASS_COPY) && map->l_type == lt_executable) - continue; - - /* Do not look into objects which are going to be removed. */ - if (map->l_removed) - continue; - - /* Print some debugging info if wanted. */ - 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); - - /* If the hash table is empty there is nothing to do here. */ - 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]); - - const ElfW(Sym) *sym; - const ElfW(Addr) *bitmask = map->l_gnu_bitmask; - if (__glibc_likely (bitmask != NULL)) - { - ElfW(Addr) bitmask_word - = bitmask[(new_hash / __ELF_NATIVE_CLASS) - & map->l_gnu_bitmask_idxbits]; - - unsigned int hashbit1 = new_hash & (__ELF_NATIVE_CLASS - 1); - unsigned int hashbit2 = ((new_hash >> map->l_gnu_shift) - & (__ELF_NATIVE_CLASS - 1)); - - if (__glibc_unlikely ((bitmask_word >> hashbit1) - & (bitmask_word >> hashbit2) & 1)) - { - Elf32_Word bucket = map->l_gnu_buckets[new_hash - % map->l_nbuckets]; - if (bucket != 0) - { - const Elf32_Word *hasharr = &map->l_gnu_chain_zero[bucket]; - - do - if (((*hasharr ^ new_hash) >> 1) == 0) - { - symidx = hasharr - map->l_gnu_chain_zero; - 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; - } - while ((*hasharr++ & 1u) == 0); - } - } - /* No symbol found. */ - symidx = SHN_UNDEF; - } - else - { - if (*old_hash == 0xffffffff) - *old_hash = _dl_elf_hash (undef_name); - - /* Use the old SysV-style hash table. Search the appropriate - hash bucket in this object's symbol table for a definition - for the same symbol name. */ - for (symidx = map->l_buckets[*old_hash % map->l_nbuckets]; - symidx != STN_UNDEF; - symidx = map->l_chain[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; - } - } - - /* If we have seen exactly one versioned symbol while we are - looking for an unversioned symbol and the version is not the - default version we still accept this symbol since there are - no possible ambiguities. */ - sym = num_versions == 1 ? versioned_sym : NULL; - - if (sym != NULL) - { - found_it: - /* 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 - } - - /* Hidden and internal symbols are local, ignore them. */ - if (__glibc_unlikely (dl_symbol_visibility_binds_local_p (sym))) - goto skip; - - switch (ELFW(ST_BIND) (sym->st_info)) - { - case STB_WEAK: - /* Weak definition. Use this value if we don't find another. */ - if (__glibc_unlikely (GLRO(dl_dynamic_weak))) - { - if (! result->s) - { - result->s = sym; - result->m = (struct link_map *) map; - } - break; - } - /* FALLTHROUGH */ - case STB_GLOBAL: - /* Global definition. Just what we need. */ - result->s = sym; - result->m = (struct link_map *) map; - return 1; - - case STB_GNU_UNIQUE:; - do_lookup_unique (undef_name, new_hash, map, result, type_class, - sym, strtab, ref, undef_map); - return 1; - - default: - /* Local symbols are ignored. */ - break; - } - } - -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 - && __glibc_unlikely (_dl_name_match_p (version->filename, map))) - return -1; - } - while (++i < n); - - /* We have not found anything until now. */ - return 0; -} - - -static uint_fast32_t -dl_new_hash (const char *s) -{ - uint_fast32_t h = 5381; - for (unsigned char c = *s; c != '\0'; c = *++s) - h = h * 33 + c; - return h & 0xffffffff; -} - - -/* Add extra dependency on MAP to UNDEF_MAP. */ -static int -internal_function -add_dependency (struct link_map *undef_map, struct link_map *map, int flags) -{ - struct link_map *runp; - unsigned int i; - int result = 0; - - /* Avoid self-references and references to objects which cannot be - unloaded anyway. */ - if (undef_map == map) - return 0; - - /* Avoid references to objects which cannot be unloaded anyway. */ - assert (map->l_type == lt_loaded); - if ((map->l_flags_1 & DF_1_NODELETE) != 0) - return 0; - - struct link_map_reldeps *l_reldeps - = atomic_forced_read (undef_map->l_reldeps); - - /* Make sure l_reldeps is read before l_initfini. */ - atomic_read_barrier (); - - /* Determine whether UNDEF_MAP already has a reference to MAP. First - look in the normal dependencies. */ - struct link_map **l_initfini = atomic_forced_read (undef_map->l_initfini); - if (l_initfini != NULL) - { - for (i = 0; l_initfini[i] != NULL; ++i) - if (l_initfini[i] == map) - return 0; - } - - /* No normal dependency. See whether we already had to add it - to the special list of dynamic dependencies. */ - unsigned int l_reldepsact = 0; - if (l_reldeps != NULL) - { - struct link_map **list = &l_reldeps->list[0]; - l_reldepsact = l_reldeps->act; - for (i = 0; i < l_reldepsact; ++i) - if (list[i] == map) - return 0; - } - - /* Save serial number of the target MAP. */ - unsigned long long serial = map->l_serial; - - /* Make sure nobody can unload the object while we are at it. */ - 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. */ - THREAD_GSCOPE_RESET_FLAG (); - __rtld_lock_lock_recursive (GL(dl_load_lock)); - /* While MAP value won't change, after THREAD_GSCOPE_RESET_FLAG () - it can e.g. point to unallocated memory. So avoid the optimizer - treating the above read from MAP->l_serial as ensurance it - can safely dereference it. */ - map = atomic_forced_read (map); - - /* From this point on it is unsafe to dereference MAP, until it - has been found in one of the lists. */ - - /* Redo the l_initfini check in case undef_map's l_initfini - changed in the mean time. */ - if (undef_map->l_initfini != l_initfini - && undef_map->l_initfini != NULL) - { - l_initfini = undef_map->l_initfini; - for (i = 0; l_initfini[i] != NULL; ++i) - if (l_initfini[i] == map) - goto out_check; - } - - /* Redo the l_reldeps check if undef_map's l_reldeps changed in - the mean time. */ - if (undef_map->l_reldeps != NULL) - { - if (undef_map->l_reldeps != l_reldeps) - { - struct link_map **list = &undef_map->l_reldeps->list[0]; - l_reldepsact = undef_map->l_reldeps->act; - for (i = 0; i < l_reldepsact; ++i) - if (list[i] == map) - goto out_check; - } - else if (undef_map->l_reldeps->act > l_reldepsact) - { - struct link_map **list - = &undef_map->l_reldeps->list[0]; - i = l_reldepsact; - l_reldepsact = undef_map->l_reldeps->act; - for (; i < l_reldepsact; ++i) - if (list[i] == map) - goto out_check; - } - } - } - else - __rtld_lock_lock_recursive (GL(dl_load_lock)); - - /* The object is not yet in the dependency list. Before we add - it make sure just one more time the object we are about to - reference is still available. There is a brief period in - which the object could have been removed since we found the - definition. */ - runp = GL(dl_ns)[undef_map->l_ns]._ns_loaded; - while (runp != NULL && runp != map) - runp = runp->l_next; - - if (runp != NULL) - { - /* The object is still available. */ - - /* MAP could have been dlclosed, freed and then some other dlopened - library could have the same link_map pointer. */ - if (map->l_serial != serial) - goto out_check; - - /* Redo the NODELETE check, as when dl_load_lock wasn't held - yet this could have changed. */ - if ((map->l_flags_1 & DF_1_NODELETE) != 0) - goto out; - - /* If the object with the undefined reference cannot be removed ever - just make sure the same is true for the object which contains the - definition. */ - if (undef_map->l_type != lt_loaded - || (undef_map->l_flags_1 & DF_1_NODELETE) != 0) - { - map->l_flags_1 |= DF_1_NODELETE; - goto out; - } - - /* Add the reference now. */ - 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 - `realloc'. */ - struct link_map_reldeps *newp; - unsigned int max - = undef_map->l_reldepsmax ? undef_map->l_reldepsmax * 2 : 10; - -#ifdef RTLD_PREPARE_FOREIGN_CALL - RTLD_PREPARE_FOREIGN_CALL; -#endif - - newp = malloc (sizeof (*newp) + max * sizeof (struct link_map *)); - if (newp == NULL) - { - /* If we didn't manage to allocate memory for the list this is - no fatal problem. We simply make sure the referenced object - cannot be unloaded. This is semantically the correct - behavior. */ - map->l_flags_1 |= DF_1_NODELETE; - goto out; - } - else - { - if (l_reldepsact) - memcpy (&newp->list[0], &undef_map->l_reldeps->list[0], - l_reldepsact * sizeof (struct link_map *)); - newp->list[l_reldepsact] = map; - newp->act = l_reldepsact + 1; - atomic_write_barrier (); - void *old = undef_map->l_reldeps; - undef_map->l_reldeps = newp; - undef_map->l_reldepsmax = max; - if (old) - _dl_scope_free (old); - } - } - else - { - undef_map->l_reldeps->list[l_reldepsact] = map; - atomic_write_barrier (); - undef_map->l_reldeps->act = l_reldepsact + 1; - } - - /* Display information if we are debugging. */ - 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), - map->l_ns, - DSO_FILENAME (undef_map->l_name), - undef_map->l_ns); - } - else - /* Whoa, that was bad luck. We have to search again. */ - result = -1; - - out: - /* Release the lock. */ - __rtld_lock_unlock_recursive (GL(dl_load_lock)); - - if (__glibc_unlikely (flags & DL_LOOKUP_GSCOPE_LOCK)) - THREAD_GSCOPE_SET_FLAG (); - - return result; - - out_check: - if (map->l_serial != serial) - result = -1; - goto out; -} - -static void -internal_function -_dl_debug_bindings (const char *undef_name, struct link_map *undef_map, - const ElfW(Sym) **ref, struct sym_val *value, - const struct r_found_version *version, int type_class, - int protected); - - -/* Search loaded objects' symbol tables for a definition of the symbol - UNDEF_NAME, perhaps with a requested version for the symbol. - - We must never have calls to the audit functions inside this function - or in any function which gets called. If this would happen the audit - code might create a thread which can throw off all the scope locking. */ -lookup_t -internal_function -_dl_lookup_symbol_x (const char *undef_name, struct link_map *undef_map, - const ElfW(Sym) **ref, - struct r_scope_elem *symbol_scope[], - const struct r_found_version *version, - int type_class, int flags, struct link_map *skip_map) -{ - const uint_fast32_t new_hash = dl_new_hash (undef_name); - unsigned long int old_hash = 0xffffffff; - struct sym_val current_value = { NULL, NULL }; - struct r_scope_elem **scope = symbol_scope; - - bump_num_relocations (); - - /* No other flag than DL_LOOKUP_ADD_DEPENDENCY or DL_LOOKUP_GSCOPE_LOCK - is allowed if we look up a versioned symbol. */ - assert (version == NULL - || (flags & ~(DL_LOOKUP_ADD_DEPENDENCY | DL_LOOKUP_GSCOPE_LOCK)) - == 0); - - size_t i = 0; - if (__glibc_unlikely (skip_map != NULL)) - /* Search the relevant loaded objects for a definition. */ - while ((*scope)->r_list[i] != skip_map) - ++i; - - /* Search the relevant loaded objects for a definition. */ - for (size_t start = i; *scope != NULL; start = 0, ++scope) - { - int res = do_lookup_x (undef_name, new_hash, &old_hash, *ref, - ¤t_value, *scope, start, version, flags, - skip_map, type_class, undef_map); - if (res > 0) - break; - - 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 - for unversioned lookups. */ - assert (version != NULL); - const char *reference_name = undef_map ? undef_map->l_name : ""; - - /* XXX We cannot translate the message. */ - _dl_signal_cerror (0, DSO_FILENAME (reference_name), - N_("relocation error"), - make_string ("symbol ", undef_name, ", version ", - version->name, - " not defined in file ", - version->filename, - " with link time reference", - res == -2 - ? " (no version symbols)" : "")); - *ref = NULL; - return 0; - } - } - - if (__glibc_unlikely (current_value.s == NULL)) - { - if ((*ref == NULL || ELFW(ST_BIND) ((*ref)->st_info) != STB_WEAK) - && !(GLRO(dl_debug_mask) & DL_DEBUG_UNUSED)) - { - /* We could find no value for a strong reference. */ - const char *reference_name = undef_map ? undef_map->l_name : ""; - const char *versionstr = version ? ", version " : ""; - const char *versionname = (version && version->name - ? version->name : ""); - - /* XXX We cannot translate the message. */ - _dl_signal_cerror (0, DSO_FILENAME (reference_name), - N_("symbol lookup error"), - make_string ("undefined symbol: ", undef_name, - versionstr, versionname)); - } - *ref = NULL; - return 0; - } - - int protected = (*ref - && ELFW(ST_VISIBILITY) ((*ref)->st_other) == STV_PROTECTED); - if (__glibc_unlikely (protected != 0)) - { - /* It is very tricky. We need to figure out what value to - return for the protected symbol. */ - if (type_class == ELF_RTYPE_CLASS_PLT) - { - if (current_value.s != NULL && current_value.m != undef_map) - { - current_value.s = *ref; - current_value.m = undef_map; - } - } - else - { - struct sym_val protected_value = { NULL, NULL }; - - 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_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) - { - current_value.s = *ref; - current_value.m = undef_map; - } - } - } - - /* We have to check whether this would bind UNDEF_MAP to an object - 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 (__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 - /* Add UNDEF_MAP to the dependencies. */ - && add_dependency (undef_map, current_value.m, flags) < 0) - /* Something went wrong. Perhaps the object we tried to reference - was just removed. Try finding another definition. */ - return _dl_lookup_symbol_x (undef_name, undef_map, ref, - (flags & DL_LOOKUP_GSCOPE_LOCK) - ? undef_map->l_scope : symbol_scope, - version, type_class, flags, skip_map); - - /* The object is used. */ - if (__glibc_unlikely (current_value.m->l_used == 0)) - current_value.m->l_used = 1; - - if (__glibc_unlikely (GLRO(dl_debug_mask) - & (DL_DEBUG_BINDINGS|DL_DEBUG_PRELINK))) - _dl_debug_bindings (undef_name, undef_map, ref, - ¤t_value, version, type_class, protected); - - *ref = current_value.s; - return LOOKUP_VALUE (current_value.m); -} - - -/* Cache the location of MAP's hash table. */ - -void -internal_function -_dl_setup_hash (struct link_map *map) -{ - Elf_Symndx *hash; - - if (__glibc_likely (map->l_info[DT_ADDRTAGIDX (DT_GNU_HASH) + DT_NUM - + DT_THISPROCNUM + DT_VERSIONTAGNUM - + DT_EXTRANUM + DT_VALNUM] != NULL)) - { - Elf32_Word *hash32 - = (void *) D_PTR (map, l_info[DT_ADDRTAGIDX (DT_GNU_HASH) + DT_NUM - + DT_THISPROCNUM + DT_VERSIONTAGNUM - + DT_EXTRANUM + DT_VALNUM]); - map->l_nbuckets = *hash32++; - Elf32_Word symbias = *hash32++; - Elf32_Word bitmask_nwords = *hash32++; - /* Must be a power of two. */ - assert ((bitmask_nwords & (bitmask_nwords - 1)) == 0); - map->l_gnu_bitmask_idxbits = bitmask_nwords - 1; - map->l_gnu_shift = *hash32++; - - map->l_gnu_bitmask = (ElfW(Addr) *) hash32; - hash32 += __ELF_NATIVE_CLASS / 32 * bitmask_nwords; - - map->l_gnu_buckets = hash32; - hash32 += map->l_nbuckets; - map->l_gnu_chain_zero = hash32 - symbias; - return; - } - - if (!map->l_info[DT_HASH]) - return; - hash = (void *) D_PTR (map, l_info[DT_HASH]); - - map->l_nbuckets = *hash++; - /* Skip nchain. */ - hash++; - map->l_buckets = hash; - hash += map->l_nbuckets; - map->l_chain = hash; -} - - -static void -internal_function -_dl_debug_bindings (const char *undef_name, struct link_map *undef_map, - const ElfW(Sym) **ref, struct sym_val *value, - const struct r_found_version *version, int type_class, - int protected) -{ - const char *reference_name = undef_map->l_name; - - if (GLRO(dl_debug_mask) & DL_DEBUG_BINDINGS) - { - _dl_debug_printf ("binding file %s [%lu] to %s [%lu]: %s symbol `%s'", - DSO_FILENAME (reference_name), - undef_map->l_ns, - DSO_FILENAME (value->m->l_name), - value->m->l_ns, - protected ? "protected" : "normal", undef_name); - if (version) - _dl_debug_printf_c (" [%s]\n", version->name); - else - _dl_debug_printf_c ("\n"); - } -#ifdef SHARED - if (GLRO(dl_debug_mask) & DL_DEBUG_PRELINK) - { -/* ELF_RTYPE_CLASS_XXX must match RTYPE_CLASS_XXX used by prelink with - LD_TRACE_PRELINKING. */ -#define RTYPE_CLASS_VALID 8 -#define RTYPE_CLASS_PLT (8|1) -#define RTYPE_CLASS_COPY (8|2) -#define RTYPE_CLASS_TLS (8|4) -#if ELF_RTYPE_CLASS_PLT != 0 && ELF_RTYPE_CLASS_PLT != 1 -# error ELF_RTYPE_CLASS_PLT must be 0 or 1! -#endif -#if ELF_RTYPE_CLASS_COPY != 0 && ELF_RTYPE_CLASS_COPY != 2 -# error ELF_RTYPE_CLASS_COPY must be 0 or 2! -#endif - int conflict = 0; - struct sym_val val = { NULL, NULL }; - - if ((GLRO(dl_trace_prelink_map) == NULL - || GLRO(dl_trace_prelink_map) == GL(dl_ns)[LM_ID_BASE]._ns_loaded) - && undef_map != GL(dl_ns)[LM_ID_BASE]._ns_loaded) - { - const uint_fast32_t new_hash = dl_new_hash (undef_name); - unsigned long int old_hash = 0xffffffff; - struct unique_sym *saved_entries - = GL(dl_ns)[LM_ID_BASE]._ns_unique_sym_table.entries; - - GL(dl_ns)[LM_ID_BASE]._ns_unique_sym_table.entries = NULL; - do_lookup_x (undef_name, new_hash, &old_hash, *ref, &val, - undef_map->l_local_scope[0], 0, version, 0, NULL, - type_class, undef_map); - if (val.s != value->s || val.m != value->m) - conflict = 1; - else if (__glibc_unlikely (undef_map->l_symbolic_in_local_scope) - && val.s - && __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 - can be conflicts even if the above is equal. As symbol - resolution goes from the last library to the first and - if a STB_GNU_UNIQUE symbol is found in some late DT_SYMBOLIC - library, it would be the one that is looked up. */ - struct sym_val val2 = { NULL, NULL }; - size_t n; - struct r_scope_elem *scope = undef_map->l_local_scope[0]; - - for (n = 0; n < scope->r_nlist; n++) - if (scope->r_list[n] == val.m) - break; - - for (n++; n < scope->r_nlist; n++) - if (scope->r_list[n]->l_info[DT_SYMBOLIC] != NULL - && do_lookup_x (undef_name, new_hash, &old_hash, *ref, - &val2, - &scope->r_list[n]->l_symbolic_searchlist, - 0, version, 0, NULL, type_class, - undef_map) > 0) - { - conflict = 1; - val = val2; - break; - } - } - GL(dl_ns)[LM_ID_BASE]._ns_unique_sym_table.entries = saved_entries; - } - - if (value->s) - { - /* Keep only ELF_RTYPE_CLASS_PLT and ELF_RTYPE_CLASS_COPY - bits since since prelink only uses them. */ - type_class &= ELF_RTYPE_CLASS_PLT | ELF_RTYPE_CLASS_COPY; - if (__glibc_unlikely (ELFW(ST_TYPE) (value->s->st_info) - == STT_TLS)) - /* Clear the RTYPE_CLASS_VALID bit in RTYPE_CLASS_TLS. */ - type_class = RTYPE_CLASS_TLS & ~RTYPE_CLASS_VALID; - else if (__glibc_unlikely (ELFW(ST_TYPE) (value->s->st_info) - == STT_GNU_IFUNC)) - /* Set the RTYPE_CLASS_VALID bit. */ - type_class |= RTYPE_CLASS_VALID; - } - - if (conflict - || GLRO(dl_trace_prelink_map) == undef_map - || GLRO(dl_trace_prelink_map) == NULL - || type_class >= 4) - { - _dl_printf ("%s 0x%0*Zx 0x%0*Zx -> 0x%0*Zx 0x%0*Zx ", - conflict ? "conflict" : "lookup", - (int) sizeof (ElfW(Addr)) * 2, - (size_t) undef_map->l_map_start, - (int) sizeof (ElfW(Addr)) * 2, - (size_t) (((ElfW(Addr)) *ref) - undef_map->l_map_start), - (int) sizeof (ElfW(Addr)) * 2, - (size_t) (value->s ? value->m->l_map_start : 0), - (int) sizeof (ElfW(Addr)) * 2, - (size_t) (value->s ? value->s->st_value : 0)); - - if (conflict) - _dl_printf ("x 0x%0*Zx 0x%0*Zx ", - (int) sizeof (ElfW(Addr)) * 2, - (size_t) (val.s ? val.m->l_map_start : 0), - (int) sizeof (ElfW(Addr)) * 2, - (size_t) (val.s ? val.s->st_value : 0)); - - _dl_printf ("/%x %s\n", type_class, undef_name); - } - } -#endif -} diff --git a/elf/dl-machine-reject-phdr.h b/elf/dl-machine-reject-phdr.h deleted file mode 100644 index 57253deb52..0000000000 --- a/elf/dl-machine-reject-phdr.h +++ /dev/null @@ -1,34 +0,0 @@ -/* Machine-dependent program header inspection for the ELF loader. - Copyright (C) 2014-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -#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 deleted file mode 100644 index d36f9bd2f6..0000000000 --- a/elf/dl-map-segments.h +++ /dev/null @@ -1,157 +0,0 @@ -/* Map in a shared object's segments. Generic version. - Copyright (C) 1995-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -#include <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. */ - if (__glibc_unlikely - (__mprotect ((caddr_t) (l->l_addr + c->mapend), - loadcmds[nloadcmds - 1].mapstart - c->mapend, - PROT_NONE) < 0)) - return DL_MAP_SEGMENTS_ERROR_MPROTECT; - } - - 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 deleted file mode 100644 index 1a35baff2e..0000000000 --- a/elf/dl-minimal.c +++ /dev/null @@ -1,380 +0,0 @@ -/* Minimal replacements for basic facilities used in the dynamic linker. - Copyright (C) 1995-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -#include <errno.h> -#include <limits.h> -#include <stdio.h> -#include <string.h> -#include <tls.h> -#include <unistd.h> -#include <sys/mman.h> -#include <sys/param.h> -#include <sys/types.h> -#include <ldsodefs.h> -#include <_itoa.h> -#include <malloc/malloc-internal.h> - -#include <assert.h> - -/* Minimal malloc allocator for used during initial link. After the - initial link, a full malloc implementation is interposed, either - the one in libc, or a different one supplied by the user through - interposition. */ - -static void *alloc_ptr, *alloc_end, *alloc_last_block; - -/* Declarations of global functions. */ -extern void weak_function free (void *ptr); -extern void * weak_function realloc (void *ptr, size_t n); -extern unsigned long int weak_function __strtoul_internal (const char *nptr, - char **endptr, - int base, - int group); -extern unsigned long int weak_function strtoul (const char *nptr, - char **endptr, int base); - - -/* Allocate an aligned memory block. */ -void * weak_function -malloc (size_t n) -{ - if (alloc_end == 0) - { - /* Consume any unused space in the last page of our data segment. */ - extern int _end attribute_hidden; - alloc_ptr = &_end; - alloc_end = (void *) 0 + (((alloc_ptr - (void *) 0) - + GLRO(dl_pagesize) - 1) - & ~(GLRO(dl_pagesize) - 1)); - } - - /* Make sure the allocation pointer is ideally aligned. */ - alloc_ptr = (void *) 0 + (((alloc_ptr - (void *) 0) + MALLOC_ALIGNMENT - 1) - & ~(MALLOC_ALIGNMENT - 1)); - - if (alloc_ptr + n >= alloc_end || n >= -(uintptr_t) alloc_ptr) - { - /* Insufficient space left; allocate another page plus one extra - page to reduce number of mmap calls. */ - caddr_t page; - size_t nup = (n + GLRO(dl_pagesize) - 1) & ~(GLRO(dl_pagesize) - 1); - if (__glibc_unlikely (nup == 0 && n != 0)) - return NULL; - nup += GLRO(dl_pagesize); - page = __mmap (0, nup, PROT_READ|PROT_WRITE, - MAP_ANON|MAP_PRIVATE, -1, 0); - if (page == MAP_FAILED) - return NULL; - if (page != alloc_end) - alloc_ptr = page; - alloc_end = page + nup; - } - - alloc_last_block = (void *) alloc_ptr; - alloc_ptr += n; - return alloc_last_block; -} - -/* We use this function occasionally since the real implementation may - be optimized when it can assume the memory it returns already is - set to NUL. */ -void * weak_function -calloc (size_t nmemb, size_t size) -{ - /* New memory from the trivial malloc above is always already cleared. - (We make sure that's true in the rare occasion it might not be, - by clearing memory in free, below.) */ - size_t bytes = nmemb * size; - -#define HALF_SIZE_T (((size_t) 1) << (8 * sizeof (size_t) / 2)) - if (__builtin_expect ((nmemb | size) >= HALF_SIZE_T, 0) - && size != 0 && bytes / size != nmemb) - return NULL; - - return malloc (bytes); -} - -/* This will rarely be called. */ -void weak_function -free (void *ptr) -{ - /* We can free only the last block allocated. */ - if (ptr == alloc_last_block) - { - /* Since this is rare, we clear the freed block here - so that calloc can presume malloc returns cleared memory. */ - memset (alloc_last_block, '\0', alloc_ptr - alloc_last_block); - alloc_ptr = alloc_last_block; - } -} - -/* This is only called with the most recent block returned by malloc. */ -void * weak_function -realloc (void *ptr, size_t n) -{ - if (ptr == NULL) - return malloc (n); - assert (ptr == alloc_last_block); - size_t old_size = alloc_ptr - alloc_last_block; - alloc_ptr = alloc_last_block; - void *new = malloc (n); - return new != ptr ? memcpy (new, ptr, old_size) : new; -} - -/* Avoid signal frobnication in setjmp/longjmp. Keeps things smaller. */ - -#include <setjmp.h> - -int weak_function -__sigjmp_save (sigjmp_buf env, int savemask __attribute__ ((unused))) -{ - env[0].__mask_was_saved = 0; - return 0; -} - -/* Define our own version of the internal function used by strerror. We - only provide the messages for some common errors. This avoids pulling - in the whole error list. */ - -char * weak_function -__strerror_r (int errnum, char *buf, size_t buflen) -{ - char *msg; - - switch (errnum) - { - case ENOMEM: - msg = (char *) "Cannot allocate memory"; - break; - case EINVAL: - msg = (char *) "Invalid argument"; - break; - case ENOENT: - msg = (char *) "No such file or directory"; - break; - case EPERM: - msg = (char *) "Operation not permitted"; - break; - case EIO: - msg = (char *) "Input/output error"; - break; - case EACCES: - msg = (char *) "Permission denied"; - break; - default: - /* No need to check buffer size, all calls in the dynamic linker - provide enough space. */ - buf[buflen - 1] = '\0'; - msg = _itoa (errnum, buf + buflen - 1, 10, 0); - msg = memcpy (msg - (sizeof ("Error ") - 1), "Error ", - sizeof ("Error ") - 1); - break; - } - - return msg; -} - -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. */ - -void weak_function -__assert_fail (const char *assertion, - const char *file, unsigned int line, const char *function) -{ - _dl_fatal_printf ("\ -Inconsistency detected by ld.so: %s: %u: %s%sAssertion `%s' failed!\n", - file, line, function ?: "", function ? ": " : "", - assertion); - -} -rtld_hidden_weak (__assert_fail) - -void weak_function -__assert_perror_fail (int errnum, - const char *file, unsigned int line, - const char *function) -{ - char errbuf[400]; - _dl_fatal_printf ("\ -Inconsistency detected by ld.so: %s: %u: %s%sUnexpected error: %s.\n", - file, line, function ?: "", function ? ": " : "", - __strerror_r (errnum, errbuf, sizeof errbuf)); - -} -rtld_hidden_weak (__assert_perror_fail) -#endif - -unsigned long int weak_function -__strtoul_internal (const char *nptr, char **endptr, int base, int group) -{ - unsigned long int result = 0; - long int sign = 1; - unsigned max_digit; - - while (*nptr == ' ' || *nptr == '\t') - ++nptr; - - if (*nptr == '-') - { - sign = -1; - ++nptr; - } - else if (*nptr == '+') - ++nptr; - - if (*nptr < '0' || *nptr > '9') - { - if (endptr != NULL) - *endptr = (char *) nptr; - return 0UL; - } - - assert (base == 0); - base = 10; - max_digit = 9; - if (*nptr == '0') - { - if (nptr[1] == 'x' || nptr[1] == 'X') - { - base = 16; - nptr += 2; - } - else - { - base = 8; - max_digit = 7; - } - } - - while (1) - { - unsigned long int digval; - if (*nptr >= '0' && *nptr <= '0' + max_digit) - digval = *nptr - '0'; - else if (base == 16) - { - if (*nptr >= 'a' && *nptr <= 'f') - digval = *nptr - 'a' + 10; - else if (*nptr >= 'A' && *nptr <= 'F') - digval = *nptr - 'A' + 10; - else - break; - } - else - break; - - if (result > ULONG_MAX / base - || (result == ULONG_MAX / base && digval > ULONG_MAX % base)) - { - errno = ERANGE; - if (endptr != NULL) - *endptr = (char *) nptr; - return ULONG_MAX; - } - result *= base; - result += digval; - ++nptr; - } - - if (endptr != NULL) - *endptr = (char *) nptr; - return result * sign; -} - - -#undef _itoa -/* We always use _itoa instead of _itoa_word in ld.so since the former - also has to be present and it is never about speed when these - functions are used. */ -char * -_itoa (unsigned long long int value, char *buflim, unsigned int base, - int upper_case) -{ - assert (! upper_case); - - do - *--buflim = _itoa_lower_digits[value % base]; - while ((value /= base) != 0); - - 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. */ -#undef strsep -#undef __strsep -char * -__strsep (char **stringp, const char *delim) -{ - char *begin; - - assert (delim[0] != '\0'); - - begin = *stringp; - if (begin != NULL) - { - char *end = begin; - - while (*end != '\0' || (end = NULL)) - { - const char *dp = delim; - - do - if (*dp == *end) - break; - while (*++dp != '\0'); - - if (*dp != '\0') - { - *end++ = '\0'; - break; - } - - ++end; - } - - *stringp = end; - } - - return begin; -} -weak_alias (__strsep, strsep) -strong_alias (__strsep, __strsep_g) diff --git a/elf/dl-misc.c b/elf/dl-misc.c deleted file mode 100644 index c5d3e0e7c5..0000000000 --- a/elf/dl-misc.c +++ /dev/null @@ -1,362 +0,0 @@ -/* Miscellaneous support functions for dynamic linker - Copyright (C) 1997-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -#include <assert.h> -#include <fcntl.h> -#include <ldsodefs.h> -#include <limits.h> -#include <link.h> -#include <stdarg.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <stdint.h> -#include <sys/mman.h> -#include <sys/param.h> -#include <sys/stat.h> -#include <sys/uio.h> -#include <sysdep.h> -#include <_itoa.h> -#include <dl-writev.h> - - -/* Read the whole contents of FILE into new mmap'd space with given - protections. *SIZEP gets the size of the file. On error MAP_FAILED - is returned. */ - -void * -internal_function -_dl_sysdep_read_whole_file (const char *file, size_t *sizep, int prot) -{ - void *result = MAP_FAILED; - struct stat64 st; - int fd = __open (file, O_RDONLY | O_CLOEXEC); - if (fd >= 0) - { - if (__fxstat64 (_STAT_VER, fd, &st) >= 0) - { - *sizep = st.st_size; - - /* No need to map the file if it is empty. */ - if (*sizep != 0) - /* Map a copy of the file contents. */ - result = __mmap (NULL, *sizep, prot, -#ifdef MAP_COPY - MAP_COPY -#else - MAP_PRIVATE -#endif -#ifdef MAP_FILE - | MAP_FILE -#endif - , fd, 0); - } - __close (fd); - } - return result; -} - - -/* Bare-bones printf implementation. This function only knows about - the formats and flags needed and can handle only up to 64 stripes in - the output. */ -static void -_dl_debug_vdprintf (int fd, int tag_p, const char *fmt, va_list arg) -{ -# define NIOVMAX 64 - struct iovec iov[NIOVMAX]; - int niov = 0; - pid_t pid = 0; - char pidbuf[12]; - - while (*fmt != '\0') - { - const char *startp = fmt; - - if (tag_p > 0) - { - /* Generate the tag line once. It consists of the PID and a - colon followed by a tab. */ - if (pid == 0) - { - char *p; - pid = __getpid (); - assert (pid >= 0 && sizeof (pid_t) <= 4); - p = _itoa (pid, &pidbuf[10], 10, 0); - while (p > pidbuf) - *--p = ' '; - pidbuf[10] = ':'; - pidbuf[11] = '\t'; - } - - /* Append to the output. */ - assert (niov < NIOVMAX); - iov[niov].iov_len = 12; - iov[niov++].iov_base = pidbuf; - - /* No more tags until we see the next newline. */ - tag_p = -1; - } - - /* Skip everything except % and \n (if tags are needed). */ - while (*fmt != '\0' && *fmt != '%' && (! tag_p || *fmt != '\n')) - ++fmt; - - /* Append constant string. */ - assert (niov < NIOVMAX); - if ((iov[niov].iov_len = fmt - startp) != 0) - iov[niov++].iov_base = (char *) startp; - - if (*fmt == '%') - { - /* It is a format specifier. */ - char fill = ' '; - int width = -1; - int prec = -1; -#if LONG_MAX != INT_MAX - int long_mod = 0; -#endif - - /* Recognize zero-digit fill flag. */ - if (*++fmt == '0') - { - fill = '0'; - ++fmt; - } - - /* See whether with comes from a parameter. Note that no other - way to specify the width is implemented. */ - if (*fmt == '*') - { - width = va_arg (arg, int); - ++fmt; - } - - /* Handle precision. */ - if (*fmt == '.' && fmt[1] == '*') - { - prec = va_arg (arg, int); - fmt += 2; - } - - /* Recognize the l modifier. It is only important on some - platforms where long and int have a different size. We - can use the same code for size_t. */ - if (*fmt == 'l' || *fmt == 'Z') - { -#if LONG_MAX != INT_MAX - long_mod = 1; -#endif - ++fmt; - } - - switch (*fmt) - { - /* Integer formatting. */ - case 'u': - case 'x': - { - /* We have to make a difference if long and int have a - different size. */ -#if LONG_MAX != INT_MAX - unsigned long int num = (long_mod - ? va_arg (arg, unsigned long int) - : va_arg (arg, unsigned int)); -#else - unsigned long int num = va_arg (arg, unsigned int); -#endif - /* We use alloca() to allocate the buffer with the most - pessimistic guess for the size. Using alloca() allows - having more than one integer formatting in a call. */ - char *buf = (char *) alloca (3 * sizeof (unsigned long int)); - char *endp = &buf[3 * sizeof (unsigned long int)]; - char *cp = _itoa (num, endp, *fmt == 'x' ? 16 : 10, 0); - - /* Pad to the width the user specified. */ - if (width != -1) - while (endp - cp < width) - *--cp = fill; - - iov[niov].iov_base = cp; - iov[niov].iov_len = endp - cp; - ++niov; - } - break; - - case 's': - /* Get the string argument. */ - iov[niov].iov_base = va_arg (arg, char *); - iov[niov].iov_len = strlen (iov[niov].iov_base); - if (prec != -1) - iov[niov].iov_len = MIN ((size_t) prec, iov[niov].iov_len); - ++niov; - break; - - case '%': - iov[niov].iov_base = (void *) fmt; - iov[niov].iov_len = 1; - ++niov; - break; - - default: - assert (! "invalid format specifier"); - } - ++fmt; - } - else if (*fmt == '\n') - { - /* See whether we have to print a single newline character. */ - if (fmt == startp) - { - iov[niov].iov_base = (char *) startp; - iov[niov++].iov_len = 1; - } - else - /* No, just add it to the rest of the string. */ - ++iov[niov - 1].iov_len; - - /* Next line, print a tag again. */ - tag_p = 1; - ++fmt; - } - } - - /* Finally write the result. */ - _dl_writev (fd, iov, niov); -} - - -/* Write to debug file. */ -void -_dl_debug_printf (const char *fmt, ...) -{ - va_list arg; - - va_start (arg, fmt); - _dl_debug_vdprintf (GLRO(dl_debug_fd), 1, fmt, arg); - va_end (arg); -} - - -/* Write to debug file but don't start with a tag. */ -void -_dl_debug_printf_c (const char *fmt, ...) -{ - va_list arg; - - va_start (arg, fmt); - _dl_debug_vdprintf (GLRO(dl_debug_fd), -1, fmt, arg); - va_end (arg); -} - - -/* Write the given file descriptor. */ -void -_dl_dprintf (int fd, const char *fmt, ...) -{ - va_list arg; - - va_start (arg, fmt); - _dl_debug_vdprintf (fd, 0, fmt, arg); - va_end (arg); -} - - -/* Test whether given NAME matches any of the names of the given object. */ -int -internal_function -_dl_name_match_p (const char *name, const struct link_map *map) -{ - if (strcmp (name, map->l_name) == 0) - return 1; - - struct libname_list *runp = map->l_libname; - - while (runp != NULL) - if (strcmp (name, runp->name) == 0) - return 1; - else - runp = runp->next; - - return 0; -} - - -unsigned long int -internal_function -_dl_higher_prime_number (unsigned long int n) -{ - /* These are primes that are near, but slightly smaller than, a - power of two. */ - static const uint32_t primes[] = { - UINT32_C (7), - UINT32_C (13), - UINT32_C (31), - UINT32_C (61), - UINT32_C (127), - UINT32_C (251), - UINT32_C (509), - UINT32_C (1021), - UINT32_C (2039), - UINT32_C (4093), - UINT32_C (8191), - UINT32_C (16381), - UINT32_C (32749), - UINT32_C (65521), - UINT32_C (131071), - UINT32_C (262139), - UINT32_C (524287), - UINT32_C (1048573), - UINT32_C (2097143), - UINT32_C (4194301), - UINT32_C (8388593), - UINT32_C (16777213), - UINT32_C (33554393), - UINT32_C (67108859), - UINT32_C (134217689), - UINT32_C (268435399), - UINT32_C (536870909), - UINT32_C (1073741789), - UINT32_C (2147483647), - /* 4294967291L */ - UINT32_C (2147483647) + UINT32_C (2147483644) - }; - - const uint32_t *low = &primes[0]; - const uint32_t *high = &primes[sizeof (primes) / sizeof (primes[0])]; - - while (low != high) - { - const uint32_t *mid = low + (high - low) / 2; - if (n > *mid) - low = mid + 1; - else - high = mid; - } - -#if 0 - /* If we've run out of primes, abort. */ - if (n > *low) - { - fprintf (stderr, "Cannot find prime bigger than %lu\n", n); - abort (); - } -#endif - - return *low; -} diff --git a/elf/dl-object.c b/elf/dl-object.c deleted file mode 100644 index 4c43235148..0000000000 --- a/elf/dl-object.c +++ /dev/null @@ -1,229 +0,0 @@ -/* Storage management for the chain of loaded shared objects. - Copyright (C) 1995-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -#include <errno.h> -#include <string.h> -#include <stdlib.h> -#include <unistd.h> -#include <ldsodefs.h> - -#include <assert.h> - - -/* Add the new link_map NEW to the end of the namespace list. */ -void -internal_function -_dl_add_to_namespace_list (struct link_map *new, Lmid_t nsid) -{ - /* We modify the list of loaded objects. */ - __rtld_lock_lock_recursive (GL(dl_load_write_lock)); - - if (GL(dl_ns)[nsid]._ns_loaded != NULL) - { - struct link_map *l = GL(dl_ns)[nsid]._ns_loaded; - while (l->l_next != NULL) - l = l->l_next; - new->l_prev = l; - /* new->l_next = NULL; Would be necessary but we use calloc. */ - l->l_next = new; - } - else - GL(dl_ns)[nsid]._ns_loaded = new; - ++GL(dl_ns)[nsid]._ns_nloaded; - new->l_serial = GL(dl_load_adds); - ++GL(dl_load_adds); - - __rtld_lock_unlock_recursive (GL(dl_load_write_lock)); -} - - -/* Allocate a `struct link_map' for a new object being loaded, - and enter it into the _dl_loaded list. */ -struct link_map * -internal_function -_dl_new_object (char *realname, const char *libname, int type, - struct link_map *loader, int mode, Lmid_t nsid) -{ - size_t libname_len = strlen (libname) + 1; - struct link_map *new; - struct libname_list *newname; -#ifdef SHARED - /* We create the map for the executable before we know whether we have - auditing libraries and if yes, how many. Assume the worst. */ - unsigned int naudit = GLRO(dl_naudit) ?: ((mode & __RTLD_OPENEXEC) - ? DL_NNS : 0); - size_t audit_space = naudit * sizeof (new->l_audit[0]); -#else -# define audit_space 0 -#endif - - new = (struct link_map *) calloc (sizeof (*new) + audit_space - + sizeof (struct link_map *) - + sizeof (*newname) + libname_len, 1); - if (new == NULL) - return NULL; - - new->l_real = new; - new->l_symbolic_searchlist.r_list = (struct link_map **) ((char *) (new + 1) - + audit_space); - - new->l_libname = newname - = (struct libname_list *) (new->l_symbolic_searchlist.r_list + 1); - newname->name = (char *) memcpy (newname + 1, libname, libname_len); - /* newname->next = NULL; We use calloc therefore not necessary. */ - newname->dont_free = 1; - - /* When we create the executable link map, or a VDSO link map, we start - with "" for the l_name. In these cases "" points to ld.so rodata - and won't get dumped during core file generation. Therefore to assist - gdb and to create more self-contained core files we adjust l_name to - point at the newly allocated copy (which will get dumped) instead of - the ld.so rodata copy. */ - new->l_name = *realname ? realname : (char *) newname->name + libname_len - 1; - new->l_type = type; - /* If we set the bit now since we know it is never used we avoid - dirtying the cache line later. */ - if ((GLRO(dl_debug_mask) & DL_DEBUG_UNUSED) == 0) - new->l_used = 1; - new->l_loader = loader; -#if NO_TLS_OFFSET != 0 - new->l_tls_offset = NO_TLS_OFFSET; -#endif - new->l_ns = nsid; - -#ifdef SHARED - for (unsigned int cnt = 0; cnt < naudit; ++cnt) - { - new->l_audit[cnt].cookie = (uintptr_t) new; - /* new->l_audit[cnt].bindflags = 0; */ - } -#endif - - /* new->l_global = 0; We use calloc therefore not necessary. */ - - /* Use the 'l_scope_mem' array by default for the 'l_scope' - information. If we need more entries we will allocate a large - array dynamically. */ - new->l_scope = new->l_scope_mem; - new->l_scope_max = sizeof (new->l_scope_mem) / sizeof (new->l_scope_mem[0]); - - /* Counter for the scopes we have to handle. */ - int idx = 0; - - if (GL(dl_ns)[nsid]._ns_loaded != NULL) - /* Add the global scope. */ - new->l_scope[idx++] = &GL(dl_ns)[nsid]._ns_loaded->l_searchlist; - - /* If we have no loader the new object acts as it. */ - if (loader == NULL) - loader = new; - else - /* Determine the local scope. */ - while (loader->l_loader != NULL) - loader = loader->l_loader; - - /* Insert the scope if it isn't the global scope we already added. */ - if (idx == 0 || &loader->l_searchlist != new->l_scope[0]) - { - if ((mode & RTLD_DEEPBIND) != 0 && idx != 0) - { - new->l_scope[1] = new->l_scope[0]; - idx = 0; - } - - new->l_scope[idx] = &loader->l_searchlist; - } - - new->l_local_scope[0] = &new->l_searchlist; - - /* Don't try to find the origin for the main map which has the name "". */ - if (realname[0] != '\0') - { - size_t realname_len = strlen (realname) + 1; - char *origin; - char *cp; - - if (realname[0] == '/') - { - /* It is an absolute path. Use it. But we have to make a - copy since we strip out the trailing slash. */ - cp = origin = (char *) malloc (realname_len); - if (origin == NULL) - { - origin = (char *) -1; - goto out; - } - } - else - { - size_t len = realname_len; - char *result = NULL; - - /* Get the current directory name. */ - origin = NULL; - do - { - char *new_origin; - - len += 128; - new_origin = (char *) realloc (origin, len); - if (new_origin == NULL) - /* We exit the loop. Note that result == NULL. */ - break; - origin = new_origin; - } - while ((result = __getcwd (origin, len - realname_len)) == NULL - && errno == ERANGE); - - if (result == NULL) - { - /* We were not able to determine the current directory. - Note that free(origin) is OK if origin == NULL. */ - free (origin); - origin = (char *) -1; - goto out; - } - - /* Find the end of the path and see whether we have to add a - slash. We could use rawmemchr but this need not be - fast. */ - cp = (strchr) (origin, '\0'); - if (cp[-1] != '/') - *cp++ = '/'; - } - - /* Add the real file name. */ - cp = __mempcpy (cp, realname, realname_len); - - /* Now remove the filename and the slash. Leave the slash if - the name is something like "/foo". */ - do - --cp; - while (*cp != '/'); - - if (cp == origin) - /* Keep the only slash which is the first character. */ - ++cp; - *cp = '\0'; - - out: - new->l_origin = origin; - } - - return new; -} diff --git a/elf/dl-open.c b/elf/dl-open.c deleted file mode 100644 index cec54db413..0000000000 --- a/elf/dl-open.c +++ /dev/null @@ -1,737 +0,0 @@ -/* Load a shared object at runtime, relocate it, and run its initializer. - Copyright (C) 1996-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -#include <assert.h> -#include <dlfcn.h> -#include <errno.h> -#include <libintl.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <sys/mman.h> /* Check whether MAP_COPY is defined. */ -#include <sys/param.h> -#include <libc-lock.h> -#include <ldsodefs.h> -#include <caller.h> -#include <sysdep-cancel.h> -#include <tls.h> -#include <stap-probe.h> -#include <atomic.h> - -#include <dl-dst.h> - - -extern int __libc_multiple_libcs; /* Defined in init-first.c. */ - -/* We must be careful not to leave us in an inconsistent state. Thus we - catch any error and re-raise it after cleaning up. */ - -struct dl_open_args -{ - const char *file; - int mode; - /* This is the caller of the dlopen() function. */ - const void *caller_dlopen; - /* This is the caller of _dl_open(). */ - const void *caller_dl_open; - struct link_map *map; - /* Namespace ID. */ - Lmid_t nsid; - /* Original parameters to the program and the current environment. */ - int argc; - char **argv; - char **env; -}; - - -static int -add_to_global (struct link_map *new) -{ - struct link_map **new_global; - unsigned int to_add = 0; - unsigned int cnt; - - /* Count the objects we have to put in the global scope. */ - for (cnt = 0; cnt < new->l_searchlist.r_nlist; ++cnt) - if (new->l_searchlist.r_list[cnt]->l_global == 0) - ++to_add; - - /* The symbols of the new objects and its dependencies are to be - introduced into the global scope that will be used to resolve - references from other dynamically-loaded objects. - - The global scope is the searchlist in the main link map. We - extend this list if necessary. There is one problem though: - since this structure was allocated very early (before the libc - is loaded) the memory it uses is allocated by the malloc()-stub - in the ld.so. When we come here these functions are not used - anymore. Instead the malloc() implementation of the libc is - used. But this means the block from the main map cannot be used - in an realloc() call. Therefore we allocate a completely new - array the first time we have to add something to the locale scope. */ - - struct link_namespaces *ns = &GL(dl_ns)[new->l_ns]; - if (ns->_ns_global_scope_alloc == 0) - { - /* This is the first dynamic object given global scope. */ - ns->_ns_global_scope_alloc - = ns->_ns_main_searchlist->r_nlist + to_add + 8; - new_global = (struct link_map **) - malloc (ns->_ns_global_scope_alloc * sizeof (struct link_map *)); - if (new_global == NULL) - { - ns->_ns_global_scope_alloc = 0; - nomem: - _dl_signal_error (ENOMEM, new->l_libname->name, NULL, - N_("cannot extend global scope")); - return 1; - } - - /* Copy over the old entries. */ - ns->_ns_main_searchlist->r_list - = memcpy (new_global, ns->_ns_main_searchlist->r_list, - (ns->_ns_main_searchlist->r_nlist - * sizeof (struct link_map *))); - } - else if (ns->_ns_main_searchlist->r_nlist + to_add - > ns->_ns_global_scope_alloc) - { - /* We have to extend the existing array of link maps in the - main map. */ - struct link_map **old_global - = GL(dl_ns)[new->l_ns]._ns_main_searchlist->r_list; - size_t new_nalloc = ((ns->_ns_global_scope_alloc + to_add) * 2); - - new_global = (struct link_map **) - malloc (new_nalloc * sizeof (struct link_map *)); - if (new_global == NULL) - goto nomem; - - memcpy (new_global, old_global, - ns->_ns_global_scope_alloc * sizeof (struct link_map *)); - - ns->_ns_global_scope_alloc = new_nalloc; - ns->_ns_main_searchlist->r_list = new_global; - - if (!RTLD_SINGLE_THREAD_P) - THREAD_GSCOPE_WAIT (); - - free (old_global); - } - - /* Now add the new entries. */ - unsigned int new_nlist = ns->_ns_main_searchlist->r_nlist; - for (cnt = 0; cnt < new->l_searchlist.r_nlist; ++cnt) - { - struct link_map *map = new->l_searchlist.r_list[cnt]; - - if (map->l_global == 0) - { - map->l_global = 1; - ns->_ns_main_searchlist->r_list[new_nlist++] = map; - - /* We modify the global scope. Report this. */ - 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); - } - } - atomic_write_barrier (); - ns->_ns_main_searchlist->r_nlist = new_nlist; - - return 0; -} - -/* Search link maps in all namespaces for the DSO that contains the object at - address ADDR. Returns the pointer to the link map of the matching DSO, or - NULL if a match is not found. */ -struct link_map * -internal_function -_dl_find_dso_for_object (const ElfW(Addr) addr) -{ - struct link_map *l; - - /* Find the highest-addressed object that ADDR is not below. */ - for (Lmid_t ns = 0; ns < GL(dl_nns); ++ns) - for (l = GL(dl_ns)[ns]._ns_loaded; l != NULL; l = l->l_next) - if (addr >= l->l_map_start && addr < l->l_map_end - && (l->l_contiguous - || _dl_addr_inside_object (l, (ElfW(Addr)) addr))) - { - assert (ns == l->l_ns); - return l; - } - return NULL; -} -rtld_hidden_def (_dl_find_dso_for_object); - -static void -dl_open_worker (void *a) -{ - struct dl_open_args *args = a; - const char *file = args->file; - int mode = args->mode; - struct link_map *call_map = NULL; - - /* Check whether _dl_open() has been called from a valid DSO. */ - if (__check_caller (args->caller_dl_open, - allow_libc|allow_libdl|allow_ldso) != 0) - _dl_signal_error (0, "dlopen", NULL, N_("invalid caller")); - - /* Determine the caller's map if necessary. This is needed in case - we have a DST, when we don't know the namespace ID we have to put - the new object in, or when the file name has no path in which - case we need to look along the RUNPATH/RPATH of the caller. */ - const char *dst = strchr (file, '$'); - if (dst != NULL || args->nsid == __LM_ID_CALLER - || strchr (file, '/') == NULL) - { - const void *caller_dlopen = args->caller_dlopen; - - /* We have to find out from which object the caller is calling. - By default we assume this is the main application. */ - call_map = GL(dl_ns)[LM_ID_BASE]._ns_loaded; - - struct link_map *l = _dl_find_dso_for_object ((ElfW(Addr)) caller_dlopen); - - if (l) - call_map = l; - - if (args->nsid == __LM_ID_CALLER) - args->nsid = call_map->l_ns; - } - - /* 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); - - /* If the pointer returned is NULL this means the RTLD_NOLOAD flag is - set and the object is not already loaded. */ - if (new == NULL) - { - assert (mode & RTLD_NOLOAD); - return; - } - - /* 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 (__glibc_unlikely (mode & __RTLD_SPROF)) - /* This happens only if we load a DSO for 'sprof'. */ - return; - - /* This object is directly loaded. */ - ++new->l_direct_opencount; - - /* It was already open. */ - if (__glibc_unlikely (new->l_searchlist.r_list != NULL)) - { - /* Let the user know about the opencount. */ - 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); - - /* If the user requested the object to be in the global namespace - but it is not so far, add it now. */ - if ((mode & RTLD_GLOBAL) && new->l_global == 0) - (void) add_to_global (new); - - assert (_dl_debug_initialize (0, args->nsid)->r_state == RT_CONSISTENT); - - return; - } - - /* Load that object's dependencies. */ - _dl_map_object_deps (new, NULL, 0, 0, - mode & (__RTLD_DLOPEN | RTLD_DEEPBIND | __RTLD_AUDIT)); - - /* So far, so good. Now check the versions. */ - for (unsigned int i = 0; i < new->l_searchlist.r_nlist; ++i) - if (new->l_searchlist.r_list[i]->l_real->l_versions == NULL) - (void) _dl_check_map_versions (new->l_searchlist.r_list[i]->l_real, - 0, 0); - -#ifdef SHARED - /* Auditing checkpoint: we have added all objects. */ - 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. */ - if (head->l_auditing == 0) - { - struct audit_ifaces *afct = GLRO(dl_audit); - for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) - { - if (afct->activity != NULL) - afct->activity (&head->l_audit[cnt].cookie, LA_ACT_CONSISTENT); - - afct = afct->next; - } - } - } -#endif - - /* Notify the debugger all new objects are now ready to go. */ - struct r_debug *r = _dl_debug_initialize (0, args->nsid); - r->r_state = RT_CONSISTENT; - _dl_debug_state (); - LIBC_PROBE (map_complete, 3, args->nsid, r, new); - - /* Print scope information. */ - 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. */ - int reloc_mode = mode & __RTLD_AUDIT; - if (GLRO(dl_lazy)) - reloc_mode |= mode & RTLD_LAZY; - - /* Sort the objects by dependency for the relocation process. This - allows IFUNC relocations to work and it also means copy - relocation of dependencies are if necessary overwritten. */ - size_t nmaps = 0; - struct link_map *l = new; - do - { - if (! l->l_real->l_relocated) - ++nmaps; - l = l->l_next; - } - while (l != NULL); - struct link_map *maps[nmaps]; - nmaps = 0; - l = new; - do - { - if (! l->l_real->l_relocated) - maps[nmaps++] = l; - l = l->l_next; - } - while (l != NULL); - if (nmaps > 1) - { - uint16_t seen[nmaps]; - memset (seen, '\0', sizeof (seen)); - size_t i = 0; - while (1) - { - ++seen[i]; - struct link_map *thisp = maps[i]; - - /* Find the last object in the list for which the current one is - a dependency and move the current object behind the object - with the dependency. */ - size_t k = nmaps - 1; - while (k > i) - { - struct link_map **runp = maps[k]->l_initfini; - if (runp != NULL) - /* Look through the dependencies of the object. */ - while (*runp != NULL) - if (__glibc_unlikely (*runp++ == thisp)) - { - /* Move the current object to the back past the last - object with it as the dependency. */ - memmove (&maps[i], &maps[i + 1], - (k - i) * sizeof (maps[0])); - maps[k] = thisp; - - if (seen[i + 1] > nmaps - i) - { - ++i; - goto next_clear; - } - - uint16_t this_seen = seen[i]; - memmove (&seen[i], &seen[i + 1], - (k - i) * sizeof (seen[0])); - seen[k] = this_seen; - - goto next; - } - - --k; - } - - if (++i == nmaps) - break; - next_clear: - memset (&seen[i], 0, (nmaps - i) * sizeof (seen[0])); - next:; - } - } - - int relocation_in_progress = 0; - - for (size_t i = nmaps; i-- > 0; ) - { - l = maps[i]; - - if (! relocation_in_progress) - { - /* Notify the debugger that relocations are about to happen. */ - LIBC_PROBE (reloc_start, 2, args->nsid, r); - relocation_in_progress = 1; - } - -#ifdef SHARED - 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 - this is necessary or not by observing the `_dl_profile_map' - variable. If it was NULL but is not NULL afterwards we must - start the profiling. */ - struct link_map *old_profile_map = GL(dl_profile_map); - - _dl_relocate_object (l, l->l_scope, reloc_mode | RTLD_LAZY, 1); - - if (old_profile_map == NULL && GL(dl_profile_map) != NULL) - { - /* We must prepare the profiling. */ - _dl_start_profile (); - - /* Prevent unloading the object. */ - GL(dl_profile_map)->l_flags_1 |= DF_1_NODELETE; - } - } - else -#endif - _dl_relocate_object (l, l->l_scope, reloc_mode, 0); - } - - /* If the file is not loaded now as a dependency, add the search - list of the newly loaded object to the scope. */ - bool any_tls = false; - unsigned int first_static_tls = new->l_searchlist.r_nlist; - for (unsigned int i = 0; i < new->l_searchlist.r_nlist; ++i) - { - struct link_map *imap = new->l_searchlist.r_list[i]; - int from_scope = 0; - - /* If the initializer has been called already, the object has - not been loaded here and now. */ - if (imap->l_init_called && imap->l_type == lt_loaded) - { - struct r_scope_elem **runp = imap->l_scope; - size_t cnt = 0; - - while (*runp != NULL) - { - if (*runp == &new->l_searchlist) - break; - ++cnt; - ++runp; - } - - if (*runp != NULL) - /* Avoid duplicates. */ - continue; - - if (__glibc_unlikely (cnt + 1 >= imap->l_scope_max)) - { - /* The 'r_scope' array is too small. Allocate a new one - dynamically. */ - size_t new_size; - struct r_scope_elem **newp; - -#define SCOPE_ELEMS(imap) \ - (sizeof (imap->l_scope_mem) / sizeof (imap->l_scope_mem[0])) - - if (imap->l_scope != imap->l_scope_mem - && imap->l_scope_max < SCOPE_ELEMS (imap)) - { - new_size = SCOPE_ELEMS (imap); - newp = imap->l_scope_mem; - } - else - { - new_size = imap->l_scope_max * 2; - newp = (struct r_scope_elem **) - malloc (new_size * sizeof (struct r_scope_elem *)); - if (newp == NULL) - _dl_signal_error (ENOMEM, "dlopen", NULL, - N_("cannot create scope list")); - } - - memcpy (newp, imap->l_scope, cnt * sizeof (imap->l_scope[0])); - struct r_scope_elem **old = imap->l_scope; - - imap->l_scope = newp; - - if (old != imap->l_scope_mem) - _dl_scope_free (old); - - imap->l_scope_max = new_size; - } - - /* First terminate the extended list. Otherwise a thread - might use the new last element and then use the garbage - at offset IDX+1. */ - imap->l_scope[cnt + 1] = NULL; - atomic_write_barrier (); - imap->l_scope[cnt] = &new->l_searchlist; - - /* Print only new scope information. */ - from_scope = cnt; - } - /* Only add TLS memory if this object is loaded now and - therefore is not yet initialized. */ - else if (! imap->l_init_called - /* Only if the module defines thread local data. */ - && __builtin_expect (imap->l_tls_blocksize > 0, 0)) - { - /* Now that we know the object is loaded successfully add - modules containing TLS data to the slot info table. We - might have to increase its size. */ - _dl_add_to_slotinfo (imap); - - if (imap->l_need_tls_init - && first_static_tls == new->l_searchlist.r_nlist) - first_static_tls = i; - - /* We have to bump the generation counter. */ - any_tls = true; - } - - /* Print scope information. */ - if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_SCOPES)) - _dl_show_scope (imap, from_scope); - } - - /* Bump the generation number if necessary. */ - if (any_tls && __builtin_expect (++GL(dl_tls_generation) == 0, 0)) - _dl_fatal_printf (N_("\ -TLS generation counter wrapped! Please report this.")); - - /* We need a second pass for static tls data, because _dl_update_slotinfo - must not be run while calls to _dl_add_to_slotinfo are still pending. */ - for (unsigned int i = first_static_tls; i < new->l_searchlist.r_nlist; ++i) - { - struct link_map *imap = new->l_searchlist.r_list[i]; - - if (imap->l_need_tls_init - && ! imap->l_init_called - && imap->l_tls_blocksize > 0) - { - /* For static TLS we have to allocate the memory here and - 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 - generation of the DSO we are allocating data for. */ - _dl_update_slotinfo (imap->l_tls_modid); -#endif - - GL(dl_init_static_tls) (imap); - assert (imap->l_need_tls_init == 0); - } - } - - /* Notify the debugger all new objects have been relocated. */ - if (relocation_in_progress) - LIBC_PROBE (reloc_complete, 3, args->nsid, r, new); - -#ifndef SHARED - DL_STATIC_INIT (new); -#endif - - /* Run the initializer functions of new objects. */ - _dl_init (new, args->argc, args->argv, args->env); - - /* Now we can make the new map available in the global scope. */ - if (mode & RTLD_GLOBAL) - /* Move the object in the global namespace. */ - if (add_to_global (new) != 0) - /* It failed. */ - return; - -#ifndef SHARED - /* We must be the static _dl_open in libc.a. A static program that - has loaded a dynamic object now has competition. */ - __libc_multiple_libcs = 1; -#endif - - /* Let the user know about the opencount. */ - 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); -} - - -void * -_dl_open (const char *file, int mode, const void *caller_dlopen, Lmid_t nsid, - int argc, char *argv[], char *env[]) -{ - if ((mode & RTLD_BINDING_MASK) == 0) - /* One of the flags must be set. */ - _dl_signal_error (EINVAL, file, NULL, N_("invalid mode for dlopen()")); - - /* Make sure we are alone. */ - __rtld_lock_lock_recursive (GL(dl_load_lock)); - - 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 (__glibc_unlikely (nsid == DL_NNS)) - { - /* No more namespace available. */ - __rtld_lock_unlock_recursive (GL(dl_load_lock)); - - _dl_signal_error (EINVAL, file, NULL, N_("\ -no more namespaces available for dlmopen()")); - } - else if (nsid == GL(dl_nns)) - { - __rtld_lock_initialize (GL(dl_ns)[nsid]._ns_unique_sym_table.lock); - ++GL(dl_nns); - } - - _dl_debug_initialize (0, nsid)->r_state = RT_CONSISTENT; - } - /* 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 (__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()")); - - struct dl_open_args args; - args.file = file; - args.mode = mode; - args.caller_dlopen = caller_dlopen; - args.caller_dl_open = RETURN_ADDRESS (0); - args.map = NULL; - args.nsid = nsid; - args.argc = argc; - args.argv = argv; - args.env = env; - - const char *objname; - const char *errstring; - bool malloced; - int errcode = _dl_catch_error (&objname, &errstring, &malloced, - dl_open_worker, &args); - -#if defined USE_LDCONFIG && !defined MAP_COPY - /* We must unmap the cache file. */ - _dl_unload_cache (); -#endif - - /* See if an error occurred during loading. */ - if (__glibc_unlikely (errstring != NULL)) - { - /* Remove the object from memory. It may be in an inconsistent - state if relocation failed, for example. */ - if (args.map) - { - /* Maybe some of the modules which were loaded use TLS. - Since it will be removed in the following _dl_close call - we have to mark the dtv array as having gaps to fill the - holes. This is a pessimistic assumption which won't hurt - if not true. There is no need to do this when we are - loading the auditing DSOs since TLS has not yet been set - up. */ - if ((mode & __RTLD_AUDIT) == 0) - GL(dl_tls_dtv_gaps) = true; - - _dl_close_worker (args.map, true); - } - - assert (_dl_debug_initialize (0, args.nsid)->r_state == RT_CONSISTENT); - - /* Release the lock. */ - __rtld_lock_unlock_recursive (GL(dl_load_lock)); - - /* Make a local copy of the error string so that we can release the - memory allocated for it. */ - size_t len_errstring = strlen (errstring) + 1; - char *local_errstring; - if (objname == errstring + len_errstring) - { - size_t total_len = len_errstring + strlen (objname) + 1; - local_errstring = alloca (total_len); - memcpy (local_errstring, errstring, total_len); - objname = local_errstring + len_errstring; - } - else - { - local_errstring = alloca (len_errstring); - memcpy (local_errstring, errstring, len_errstring); - } - - if (malloced) - free ((char *) errstring); - - /* Reraise the error. */ - _dl_signal_error (errcode, objname, NULL, local_errstring); - } - - assert (_dl_debug_initialize (0, args.nsid)->r_state == RT_CONSISTENT); - - /* Release the lock. */ - __rtld_lock_unlock_recursive (GL(dl_load_lock)); - - return args.map; -} - - -void -_dl_show_scope (struct link_map *l, int from) -{ - _dl_debug_printf ("object=%s [%lu]\n", - DSO_FILENAME (l->l_name), l->l_ns); - if (l->l_scope != NULL) - for (int scope_cnt = from; l->l_scope[scope_cnt] != NULL; ++scope_cnt) - { - _dl_debug_printf (" scope %u:", scope_cnt); - - for (unsigned int cnt = 0; cnt < l->l_scope[scope_cnt]->r_nlist; ++cnt) - if (*l->l_scope[scope_cnt]->r_list[cnt]->l_name) - _dl_debug_printf_c (" %s", - l->l_scope[scope_cnt]->r_list[cnt]->l_name); - else - _dl_debug_printf_c (" %s", RTLD_PROGNAME); - - _dl_debug_printf_c ("\n"); - } - else - _dl_debug_printf (" no scope\n"); - _dl_debug_printf ("\n"); -} diff --git a/elf/dl-origin.c b/elf/dl-origin.c deleted file mode 100644 index 1e44272a8e..0000000000 --- a/elf/dl-origin.c +++ /dev/null @@ -1,50 +0,0 @@ -/* Find path of executable. - Copyright (C) 1998-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -#include <stdlib.h> -#include <string.h> -#include <sys/param.h> -#include <ldsodefs.h> - -#include <dl-dst.h> - - -const char * -_dl_get_origin (void) -{ - char *result = (char *) -1; - /* We use the environment variable LD_ORIGIN_PATH. If it is set make - a copy and strip out trailing slashes. */ - if (GLRO(dl_origin_path) != NULL) - { - size_t len = strlen (GLRO(dl_origin_path)); - result = (char *) malloc (len + 1); - if (result == NULL) - result = (char *) -1; - else - { - char *cp = __mempcpy (result, GLRO(dl_origin_path), len); - while (cp > result + 1 && cp[-1] == '/') - --cp; - *cp = '\0'; - } - } - - return result; -} diff --git a/elf/dl-profile.c b/elf/dl-profile.c deleted file mode 100644 index a4f11089a1..0000000000 --- a/elf/dl-profile.c +++ /dev/null @@ -1,596 +0,0 @@ -/* Profiling of shared libraries. - Copyright (C) 1997-2017 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. - - 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> -#include <errno.h> -#include <fcntl.h> -#include <inttypes.h> -#include <limits.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <stdint.h> -#include <ldsodefs.h> -#include <sys/gmon.h> -#include <sys/gmon_out.h> -#include <sys/mman.h> -#include <sys/param.h> -#include <sys/stat.h> -#include <atomic.h> - -/* The LD_PROFILE feature has to be implemented different to the - normal profiling using the gmon/ functions. The problem is that an - arbitrary amount of processes simulataneously can be run using - profiling and all write the results in the same file. To provide - this mechanism one could implement a complicated mechanism to merge - the content of two profiling runs or one could extend the file - format to allow more than one data set. For the second solution we - would have the problem that the file can grow in size beyond any - limit and both solutions have the problem that the concurrency of - writing the results is a big problem. - - Another much simpler method is to use mmap to map the same file in - all using programs and modify the data in the mmap'ed area and so - also automatically on the disk. Using the MAP_SHARED option of - mmap(2) this can be done without big problems in more than one - file. - - This approach is very different from the normal profiling. We have - to use the profiling data in exactly the way they are expected to - be written to disk. But the normal format used by gprof is not usable - to do this. It is optimized for size. It writes the tags as single - bytes but this means that the following 32/64 bit values are - unaligned. - - Therefore we use a new format. This will look like this - - 0 1 2 3 <- byte is 32 bit word - 0000 g m o n - 0004 *version* <- GMON_SHOBJ_VERSION - 0008 00 00 00 00 - 000c 00 00 00 00 - 0010 00 00 00 00 - - 0014 *tag* <- GMON_TAG_TIME_HIST - 0018 ?? ?? ?? ?? - ?? ?? ?? ?? <- 32/64 bit LowPC - 0018+A ?? ?? ?? ?? - ?? ?? ?? ?? <- 32/64 bit HighPC - 0018+2*A *histsize* - 001c+2*A *profrate* - 0020+2*A s e c o - 0024+2*A n d s \0 - 0028+2*A \0 \0 \0 \0 - 002c+2*A \0 \0 \0 - 002f+2*A s - - 0030+2*A ?? ?? ?? ?? <- Count data - ... ... - 0030+2*A+K ?? ?? ?? ?? - - 0030+2*A+K *tag* <- GMON_TAG_CG_ARC - 0034+2*A+K *lastused* - 0038+2*A+K ?? ?? ?? ?? - ?? ?? ?? ?? <- FromPC#1 - 0038+3*A+K ?? ?? ?? ?? - ?? ?? ?? ?? <- ToPC#1 - 0038+4*A+K ?? ?? ?? ?? <- Count#1 - ... ... ... - 0038+(2*(CN-1)+2)*A+(CN-1)*4+K ?? ?? ?? ?? - ?? ?? ?? ?? <- FromPC#CGN - 0038+(2*(CN-1)+3)*A+(CN-1)*4+K ?? ?? ?? ?? - ?? ?? ?? ?? <- ToPC#CGN - 0038+(2*CN+2)*A+(CN-1)*4+K ?? ?? ?? ?? <- Count#CGN - - We put (for now?) no basic block information in the file since this would - introduce rase conditions among all the processes who want to write them. - - `K' is the number of count entries which is computed as - - textsize / HISTFRACTION - - `CG' in the above table is the number of call graph arcs. Normally, - the table is sparse and the profiling code writes out only the those - entries which are really used in the program run. But since we must - not extend this table (the profiling file) we'll keep them all here. - So CN can be executed in advance as - - MINARCS <= textsize*(ARCDENSITY/100) <= MAXARCS - - Now the remaining question is: how to build the data structures we can - work with from this data. We need the from set and must associate the - froms with all the associated tos. We will do this by constructing this - data structures at the program start. To do this we'll simply visit all - entries in the call graph table and add it to the appropriate list. */ - -extern int __profile_frequency (void); -libc_hidden_proto (__profile_frequency) - -/* We define a special type to address the elements of the arc table. - This is basically the `gmon_cg_arc_record' format but it includes - the room for the tag and it uses real types. */ -struct here_cg_arc_record - { - uintptr_t from_pc; - uintptr_t self_pc; - /* The count field is atomically incremented in _dl_mcount, which - requires it to be properly aligned for its type, and for this - alignment to be visible to the compiler. The amount of data - before an array of this structure is calculated as - expected_size in _dl_start_profile. Everything in that - calculation is a multiple of 4 bytes (in the case of - kcountsize, because it is derived from a subtraction of - page-aligned values, and the corresponding calculation in - __monstartup also ensures it is at least a multiple of the size - of u_long), so all copies of this field do in fact have the - appropriate alignment. */ - uint32_t count __attribute__ ((aligned (__alignof__ (uint32_t)))); - } __attribute__ ((packed)); - -static struct here_cg_arc_record *data; - -/* Nonzero if profiling is under way. */ -static int running; - -/* This is the number of entry which have been incorporated in the toset. */ -static uint32_t narcs; -/* This is a pointer to the object representing the number of entries - currently in the mmaped file. At no point of time this has to be the - same as NARCS. If it is equal all entries from the file are in our - lists. */ -static volatile uint32_t *narcsp; - - -struct here_fromstruct - { - struct here_cg_arc_record volatile *here; - uint16_t link; - }; - -static volatile uint16_t *tos; - -static struct here_fromstruct *froms; -static uint32_t fromlimit; -static volatile uint32_t fromidx; - -static uintptr_t lowpc; -static size_t textsize; -static unsigned int log_hashfraction; - - - -/* Set up profiling data to profile object desribed by MAP. The output - file is found (or created) in OUTPUT_DIR. */ -void -internal_function -_dl_start_profile (void) -{ - char *filename; - int fd; - struct stat64 st; - const ElfW(Phdr) *ph; - ElfW(Addr) mapstart = ~((ElfW(Addr)) 0); - ElfW(Addr) mapend = 0; - char *hist, *cp; - size_t idx; - size_t tossize; - size_t fromssize; - uintptr_t highpc; - uint16_t *kcount; - size_t kcountsize; - struct gmon_hdr *addr = NULL; - off_t expected_size; - /* See profil(2) where this is described. */ - int s_scale; -#define SCALE_1_TO_1 0x10000L - const char *errstr = NULL; - - /* Compute the size of the sections which contain program code. */ - for (ph = GL(dl_profile_map)->l_phdr; - ph < &GL(dl_profile_map)->l_phdr[GL(dl_profile_map)->l_phnum]; ++ph) - if (ph->p_type == PT_LOAD && (ph->p_flags & PF_X)) - { - ElfW(Addr) start = (ph->p_vaddr & ~(GLRO(dl_pagesize) - 1)); - ElfW(Addr) end = ((ph->p_vaddr + ph->p_memsz + GLRO(dl_pagesize) - 1) - & ~(GLRO(dl_pagesize) - 1)); - - if (start < mapstart) - mapstart = start; - if (end > mapend) - mapend = end; - } - - /* Now we can compute the size of the profiling data. This is done - with the same formulars as in `monstartup' (see gmon.c). */ - running = 0; - lowpc = ROUNDDOWN (mapstart + GL(dl_profile_map)->l_addr, - HISTFRACTION * sizeof (HISTCOUNTER)); - highpc = ROUNDUP (mapend + GL(dl_profile_map)->l_addr, - HISTFRACTION * sizeof (HISTCOUNTER)); - textsize = highpc - lowpc; - kcountsize = textsize / HISTFRACTION; - if ((HASHFRACTION & (HASHFRACTION - 1)) == 0) - { - /* If HASHFRACTION is a power of two, mcount can use shifting - instead of integer division. Precompute shift amount. - - This is a constant but the compiler cannot compile the - expression away since the __ffs implementation is not known - to the compiler. Help the compiler by precomputing the - usual cases. */ - assert (HASHFRACTION == 2); - - if (sizeof (*froms) == 8) - log_hashfraction = 4; - else if (sizeof (*froms) == 16) - log_hashfraction = 5; - else - log_hashfraction = __ffs (HASHFRACTION * sizeof (*froms)) - 1; - } - else - log_hashfraction = -1; - tossize = textsize / HASHFRACTION; - fromlimit = textsize * ARCDENSITY / 100; - if (fromlimit < MINARCS) - fromlimit = MINARCS; - if (fromlimit > MAXARCS) - fromlimit = MAXARCS; - fromssize = fromlimit * sizeof (struct here_fromstruct); - - expected_size = (sizeof (struct gmon_hdr) - + 4 + sizeof (struct gmon_hist_hdr) + kcountsize - + 4 + 4 + fromssize * sizeof (struct here_cg_arc_record)); - - /* Create the gmon_hdr we expect or write. */ - struct real_gmon_hdr - { - char cookie[4]; - int32_t version; - char spare[3 * 4]; - } gmon_hdr; - if (sizeof (gmon_hdr) != sizeof (struct gmon_hdr) - || (offsetof (struct real_gmon_hdr, cookie) - != offsetof (struct gmon_hdr, cookie)) - || (offsetof (struct real_gmon_hdr, version) - != offsetof (struct gmon_hdr, version))) - abort (); - - memcpy (&gmon_hdr.cookie[0], GMON_MAGIC, sizeof (gmon_hdr.cookie)); - gmon_hdr.version = GMON_SHOBJ_VERSION; - memset (gmon_hdr.spare, '\0', sizeof (gmon_hdr.spare)); - - /* Create the hist_hdr we expect or write. */ - struct real_gmon_hist_hdr - { - char *low_pc; - char *high_pc; - int32_t hist_size; - int32_t prof_rate; - char dimen[15]; - char dimen_abbrev; - } hist_hdr; - if (sizeof (hist_hdr) != sizeof (struct gmon_hist_hdr) - || (offsetof (struct real_gmon_hist_hdr, low_pc) - != offsetof (struct gmon_hist_hdr, low_pc)) - || (offsetof (struct real_gmon_hist_hdr, high_pc) - != offsetof (struct gmon_hist_hdr, high_pc)) - || (offsetof (struct real_gmon_hist_hdr, hist_size) - != offsetof (struct gmon_hist_hdr, hist_size)) - || (offsetof (struct real_gmon_hist_hdr, prof_rate) - != offsetof (struct gmon_hist_hdr, prof_rate)) - || (offsetof (struct real_gmon_hist_hdr, dimen) - != offsetof (struct gmon_hist_hdr, dimen)) - || (offsetof (struct real_gmon_hist_hdr, dimen_abbrev) - != offsetof (struct gmon_hist_hdr, dimen_abbrev))) - abort (); - - hist_hdr.low_pc = (char *) mapstart; - hist_hdr.high_pc = (char *) mapend; - hist_hdr.hist_size = kcountsize / sizeof (HISTCOUNTER); - hist_hdr.prof_rate = __profile_frequency (); - if (sizeof (hist_hdr.dimen) >= sizeof ("seconds")) - { - memcpy (hist_hdr.dimen, "seconds", sizeof ("seconds")); - memset (hist_hdr.dimen + sizeof ("seconds"), '\0', - sizeof (hist_hdr.dimen) - sizeof ("seconds")); - } - else - strncpy (hist_hdr.dimen, "seconds", sizeof (hist_hdr.dimen)); - hist_hdr.dimen_abbrev = 's'; - - /* First determine the output name. We write in the directory - OUTPUT_DIR and the name is composed from the shared objects - soname (or the file name) and the ending ".profile". */ - filename = (char *) alloca (strlen (GLRO(dl_profile_output)) + 1 - + strlen (GLRO(dl_profile)) + sizeof ".profile"); - cp = __stpcpy (filename, GLRO(dl_profile_output)); - *cp++ = '/'; - __stpcpy (__stpcpy (cp, GLRO(dl_profile)), ".profile"); - - fd = __open (filename, O_RDWR | O_CREAT | O_NOFOLLOW, DEFFILEMODE); - if (fd == -1) - { - char buf[400]; - int errnum; - - /* We cannot write the profiling data so don't do anything. */ - errstr = "%s: cannot open file: %s\n"; - print_error: - errnum = errno; - if (fd != -1) - __close (fd); - _dl_error_printf (errstr, filename, - __strerror_r (errnum, buf, sizeof buf)); - return; - } - - if (__fxstat64 (_STAT_VER, fd, &st) < 0 || !S_ISREG (st.st_mode)) - { - /* Not stat'able or not a regular file => don't use it. */ - errstr = "%s: cannot stat file: %s\n"; - goto print_error; - } - - /* Test the size. If it does not match what we expect from the size - values in the map MAP we don't use it and warn the user. */ - if (st.st_size == 0) - { - /* We have to create the file. */ - char buf[GLRO(dl_pagesize)]; - - memset (buf, '\0', GLRO(dl_pagesize)); - - if (__lseek (fd, expected_size & ~(GLRO(dl_pagesize) - 1), SEEK_SET) == -1) - { - cannot_create: - errstr = "%s: cannot create file: %s\n"; - goto print_error; - } - - if (TEMP_FAILURE_RETRY (__libc_write (fd, buf, (expected_size - & (GLRO(dl_pagesize) - - 1)))) - < 0) - goto cannot_create; - } - else if (st.st_size != expected_size) - { - __close (fd); - wrong_format: - - if (addr != NULL) - __munmap ((void *) addr, expected_size); - - _dl_error_printf ("%s: file is no correct profile data file for `%s'\n", - filename, GLRO(dl_profile)); - return; - } - - addr = (struct gmon_hdr *) __mmap (NULL, expected_size, PROT_READ|PROT_WRITE, - MAP_SHARED|MAP_FILE, fd, 0); - if (addr == (struct gmon_hdr *) MAP_FAILED) - { - errstr = "%s: cannot map file: %s\n"; - goto print_error; - } - - /* We don't need the file descriptor anymore. */ - __close (fd); - - /* Pointer to data after the header. */ - hist = (char *) (addr + 1); - kcount = (uint16_t *) ((char *) hist + sizeof (uint32_t) - + sizeof (struct gmon_hist_hdr)); - - /* Compute pointer to array of the arc information. */ - narcsp = (uint32_t *) ((char *) kcount + kcountsize + sizeof (uint32_t)); - data = (struct here_cg_arc_record *) ((char *) narcsp + sizeof (uint32_t)); - - if (st.st_size == 0) - { - /* Create the signature. */ - memcpy (addr, &gmon_hdr, sizeof (struct gmon_hdr)); - - *(uint32_t *) hist = GMON_TAG_TIME_HIST; - memcpy (hist + sizeof (uint32_t), &hist_hdr, - sizeof (struct gmon_hist_hdr)); - - narcsp[-1] = GMON_TAG_CG_ARC; - } - else - { - /* Test the signature in the file. */ - if (memcmp (addr, &gmon_hdr, sizeof (struct gmon_hdr)) != 0 - || *(uint32_t *) hist != GMON_TAG_TIME_HIST - || memcmp (hist + sizeof (uint32_t), &hist_hdr, - sizeof (struct gmon_hist_hdr)) != 0 - || narcsp[-1] != GMON_TAG_CG_ARC) - goto wrong_format; - } - - /* Allocate memory for the froms data and the pointer to the tos records. */ - tos = (uint16_t *) calloc (tossize + fromssize, 1); - if (tos == NULL) - { - __munmap ((void *) addr, expected_size); - _dl_fatal_printf ("Out of memory while initializing profiler\n"); - /* NOTREACHED */ - } - - froms = (struct here_fromstruct *) ((char *) tos + tossize); - fromidx = 0; - - /* Now we have to process all the arc count entries. BTW: it is - not critical whether the *NARCSP value changes meanwhile. Before - we enter a new entry in to toset we will check that everything is - available in TOS. This happens in _dl_mcount. - - Loading the entries in reverse order should help to get the most - frequently used entries at the front of the list. */ - for (idx = narcs = MIN (*narcsp, fromlimit); idx > 0; ) - { - size_t to_index; - size_t newfromidx; - --idx; - to_index = (data[idx].self_pc / (HASHFRACTION * sizeof (*tos))); - newfromidx = fromidx++; - froms[newfromidx].here = &data[idx]; - froms[newfromidx].link = tos[to_index]; - tos[to_index] = newfromidx; - } - - /* Setup counting data. */ - if (kcountsize < highpc - lowpc) - { -#if 0 - s_scale = ((double) kcountsize / (highpc - lowpc)) * SCALE_1_TO_1; -#else - size_t range = highpc - lowpc; - size_t quot = range / kcountsize; - - if (quot >= SCALE_1_TO_1) - s_scale = 1; - else if (quot >= SCALE_1_TO_1 / 256) - s_scale = SCALE_1_TO_1 / quot; - else if (range > ULONG_MAX / 256) - s_scale = (SCALE_1_TO_1 * 256) / (range / (kcountsize / 256)); - else - s_scale = (SCALE_1_TO_1 * 256) / ((range * 256) / kcountsize); -#endif - } - else - s_scale = SCALE_1_TO_1; - - /* Start the profiler. */ - __profil ((void *) kcount, kcountsize, lowpc, s_scale); - - /* Turn on profiling. */ - running = 1; -} - - -void -_dl_mcount (ElfW(Addr) frompc, ElfW(Addr) selfpc) -{ - volatile uint16_t *topcindex; - size_t i, fromindex; - struct here_fromstruct *fromp; - - if (! running) - return; - - /* Compute relative addresses. The shared object can be loaded at - any address. The value of frompc could be anything. We cannot - restrict it in any way, just set to a fixed value (0) in case it - is outside the allowed range. These calls show up as calls from - <external> in the gprof output. */ - frompc -= lowpc; - if (frompc >= textsize) - frompc = 0; - selfpc -= lowpc; - if (selfpc >= textsize) - goto done; - - /* Getting here we now have to find out whether the location was - already used. If yes we are lucky and only have to increment a - counter (this also has to be atomic). If the entry is new things - are getting complicated... */ - - /* Avoid integer divide if possible. */ - if ((HASHFRACTION & (HASHFRACTION - 1)) == 0) - i = selfpc >> log_hashfraction; - else - i = selfpc / (HASHFRACTION * sizeof (*tos)); - - topcindex = &tos[i]; - fromindex = *topcindex; - - if (fromindex == 0) - goto check_new_or_add; - - fromp = &froms[fromindex]; - - /* We have to look through the chain of arcs whether there is already - an entry for our arc. */ - while (fromp->here->from_pc != frompc) - { - if (fromp->link != 0) - do - fromp = &froms[fromp->link]; - while (fromp->link != 0 && fromp->here->from_pc != frompc); - - if (fromp->here->from_pc != frompc) - { - topcindex = &fromp->link; - - check_new_or_add: - /* Our entry is not among the entries we read so far from the - data file. Now see whether we have to update the list. */ - while (narcs != *narcsp && narcs < fromlimit) - { - size_t to_index; - size_t newfromidx; - to_index = (data[narcs].self_pc - / (HASHFRACTION * sizeof (*tos))); - newfromidx = catomic_exchange_and_add (&fromidx, 1) + 1; - froms[newfromidx].here = &data[narcs]; - froms[newfromidx].link = tos[to_index]; - tos[to_index] = newfromidx; - catomic_increment (&narcs); - } - - /* If we still have no entry stop searching and insert. */ - if (*topcindex == 0) - { - uint_fast32_t newarc = catomic_exchange_and_add (narcsp, 1); - - /* In rare cases it could happen that all entries in FROMS are - occupied. So we cannot count this anymore. */ - if (newarc >= fromlimit) - goto done; - - *topcindex = catomic_exchange_and_add (&fromidx, 1) + 1; - fromp = &froms[*topcindex]; - - fromp->here = &data[newarc]; - data[newarc].from_pc = frompc; - data[newarc].self_pc = selfpc; - data[newarc].count = 0; - fromp->link = 0; - catomic_increment (&narcs); - - break; - } - - fromp = &froms[*topcindex]; - } - else - /* Found in. */ - break; - } - - /* Increment the counter. */ - catomic_increment (&fromp->here->count); - - done: - ; -} -rtld_hidden_def (_dl_mcount) diff --git a/elf/dl-profstub.c b/elf/dl-profstub.c deleted file mode 100644 index 0915e29093..0000000000 --- a/elf/dl-profstub.c +++ /dev/null @@ -1,41 +0,0 @@ -/* Helper definitions for profiling of shared libraries. - Copyright (C) 1998-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. - - 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 <elf.h> -#include <ldsodefs.h> - -/* This is the map for the shared object we profile. It is defined here - only because we test for this value being NULL or not. */ - - -void -_dl_mcount_wrapper (void *selfpc) -{ - GLRO(dl_mcount) ((ElfW(Addr)) RETURN_ADDRESS (0), (ElfW(Addr)) selfpc); -} - - -void -_dl_mcount_wrapper_check (void *selfpc) -{ - if (GL(dl_profile_map) != NULL) - GLRO(dl_mcount) ((ElfW(Addr)) RETURN_ADDRESS (0), (ElfW(Addr)) selfpc); -} -libc_hidden_def (_dl_mcount_wrapper_check) diff --git a/elf/dl-reloc.c b/elf/dl-reloc.c deleted file mode 100644 index b3c3a9bbf9..0000000000 --- a/elf/dl-reloc.c +++ /dev/null @@ -1,363 +0,0 @@ -/* Relocate a shared object and resolve its references to other loaded objects. - Copyright (C) 1995-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -#include <errno.h> -#include <libintl.h> -#include <stdlib.h> -#include <unistd.h> -#include <ldsodefs.h> -#include <sys/mman.h> -#include <sys/param.h> -#include <sys/types.h> -#include <_itoa.h> -#include <libc-pointer-arith.h> -#include "dynamic-link.h" - -/* Statistics function. */ -#ifdef SHARED -# define bump_num_cache_relocations() ++GL(dl_num_cache_relocations) -#else -# define bump_num_cache_relocations() ((void) 0) -#endif - - -/* We are trying to perform a static TLS relocation in MAP, but it was - dynamically loaded. This can only work if there is enough surplus in - the static TLS area already allocated for each running thread. If this - object's TLS segment is too big to fit, we fail. If it fits, - we set MAP->l_tls_offset and return. - This function intentionally does not return any value but signals error - directly, as static TLS should be rare and code handling it should - not be inlined as much as possible. */ -int -internal_function -_dl_try_allocate_static_tls (struct link_map *map) -{ - /* If we've already used the variable with dynamic access, or if the - alignment requirements are too high, fail. */ - if (map->l_tls_offset == FORCED_DYNAMIC_TLS_OFFSET - || map->l_tls_align > GL(dl_tls_static_align)) - { - fail: - return -1; - } - -#if TLS_TCB_AT_TP - size_t freebytes = GL(dl_tls_static_size) - GL(dl_tls_static_used); - if (freebytes < TLS_TCB_SIZE) - goto fail; - freebytes -= TLS_TCB_SIZE; - - size_t blsize = map->l_tls_blocksize + map->l_tls_firstbyte_offset; - if (freebytes < blsize) - goto fail; - - size_t n = (freebytes - blsize) / map->l_tls_align; - - size_t offset = GL(dl_tls_static_used) + (freebytes - n * map->l_tls_align - - map->l_tls_firstbyte_offset); - - map->l_tls_offset = GL(dl_tls_static_used) = offset; -#elif TLS_DTV_AT_TP - /* dl_tls_static_used includes the TCB at the beginning. */ - size_t offset = (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; - - if (used > GL(dl_tls_static_size)) - goto fail; - - map->l_tls_offset = offset; - map->l_tls_firstbyte_offset = GL(dl_tls_static_used); - GL(dl_tls_static_used) = used; -#else -# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined" -#endif - - /* If the object is not yet relocated we cannot initialize the - static TLS region. Delay it. */ - if (map->l_real->l_relocated) - { -#ifdef SHARED - if (__builtin_expect (THREAD_DTV()[0].counter != GL(dl_tls_generation), - 0)) - /* Update the slot information data for at least the generation of - the DSO we are allocating data for. */ - (void) _dl_update_slotinfo (map->l_tls_modid); -#endif - - GL(dl_init_static_tls) (map); - } - else - map->l_need_tls_init = 1; - - return 0; -} - -void -internal_function __attribute_noinline__ -_dl_allocate_static_tls (struct link_map *map) -{ - if (map->l_tls_offset == FORCED_DYNAMIC_TLS_OFFSET - || _dl_try_allocate_static_tls (map)) - { - _dl_signal_error (0, map->l_name, NULL, N_("\ -cannot allocate memory in static TLS block")); - } -} - -/* Initialize static TLS area and DTV for current (only) thread. - libpthread implementations should provide their own hook - to handle all threads. */ -void -_dl_nothread_init_static_tls (struct link_map *map) -{ -#if TLS_TCB_AT_TP - void *dest = (char *) THREAD_SELF - map->l_tls_offset; -#elif TLS_DTV_AT_TP - void *dest = (char *) THREAD_SELF + map->l_tls_offset + TLS_PRE_TCB_SIZE; -#else -# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined" -#endif - - /* 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); -} - - -void -_dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[], - int reloc_mode, int consider_profiling) -{ - struct textrels - { - caddr_t start; - size_t len; - int prot; - struct textrels *next; - } *textrels = NULL; - /* Initialize it to make the compiler happy. */ - const char *errstring = NULL; - int lazy = reloc_mode & RTLD_LAZY; - int skip_ifunc = reloc_mode & __RTLD_NOIFUNC; - -#ifdef SHARED - /* If we are auditing, install the same handlers we need for profiling. */ - if ((reloc_mode & __RTLD_AUDIT) == 0) - consider_profiling |= GLRO(dl_audit) != NULL; -#elif defined PROF - /* Never use dynamic linker profiling for gprof profiling code. */ -# define consider_profiling 0 -#endif - - if (l->l_relocated) - return; - - /* If DT_BIND_NOW is set relocate all references in this object. We - do not do this if we are profiling, of course. */ - // XXX Correct for auditing? - if (!consider_profiling - && __builtin_expect (l->l_info[DT_BIND_NOW] != NULL, 0)) - lazy = 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 (__glibc_unlikely (l->l_info[DT_TEXTREL] != NULL)) - { - /* Bletch. We must make read-only segments writable - long enough to relocate them. */ - const ElfW(Phdr) *ph; - for (ph = l->l_phdr; ph < &l->l_phdr[l->l_phnum]; ++ph) - if (ph->p_type == PT_LOAD && (ph->p_flags & PF_W) == 0) - { - struct textrels *newp; - - newp = (struct textrels *) alloca (sizeof (*newp)); - 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) - { - errstring = N_("cannot make segment writable for relocation"); - call_error: - _dl_signal_error (errno, l->l_name, NULL, errstring); - } - -#if (PF_R | PF_W | PF_X) == 7 && (PROT_READ | PROT_WRITE | PROT_EXEC) == 7 - newp->prot = (PF_TO_PROT - >> ((ph->p_flags & (PF_R | PF_W | PF_X)) * 4)) & 0xf; -#else - newp->prot = 0; - if (ph->p_flags & PF_R) - newp->prot |= PROT_READ; - if (ph->p_flags & PF_W) - newp->prot |= PROT_WRITE; - if (ph->p_flags & PF_X) - newp->prot |= PROT_EXEC; -#endif - newp->next = textrels; - textrels = newp; - } - } - - { - /* Do the actual relocation of the object's GOT and other data. */ - - /* String table object symbols. */ - const char *strtab = (const void *) D_PTR (l, l_info[DT_STRTAB]); - - /* This macro is used as a callback from the ELF_DYNAMIC_RELOCATE code. */ -#define RESOLVE_MAP(ref, version, r_type) \ - ((ELFW(ST_BIND) ((*ref)->st_info) != STB_LOCAL \ - && __glibc_likely (!dl_symbol_visibility_binds_local_p (*ref))) \ - ? ((__builtin_expect ((*ref) == l->l_lookup_cache.sym, 0) \ - && elf_machine_type_class (r_type) == l->l_lookup_cache.type_class) \ - ? (bump_num_cache_relocations (), \ - (*ref) = l->l_lookup_cache.ret, \ - l->l_lookup_cache.value) \ - : ({ lookup_t _lr; \ - int _tc = elf_machine_type_class (r_type); \ - l->l_lookup_cache.type_class = _tc; \ - l->l_lookup_cache.sym = (*ref); \ - const struct r_found_version *v = NULL; \ - if ((version) != NULL && (version)->hash != 0) \ - v = (version); \ - _lr = _dl_lookup_symbol_x (strtab + (*ref)->st_name, l, (ref), \ - scope, v, _tc, \ - DL_LOOKUP_ADD_DEPENDENCY, NULL); \ - l->l_lookup_cache.ret = (*ref); \ - l->l_lookup_cache.value = _lr; })) \ - : l) - -#include "dynamic-link.h" - - ELF_DYNAMIC_RELOCATE (l, lazy, consider_profiling, skip_ifunc); - -#ifndef PROF - 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. */ - 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); - - if (l->l_reloc_result == NULL) - { - errstring = N_("\ -%s: out of memory to store relocation results for %s\n"); - _dl_fatal_printf (errstring, RTLD_PROGNAME, l->l_name); - } - } -#endif - } - - /* Mark the object so we know this work has been done. */ - l->l_relocated = 1; - - /* Undo the segment protection changes. */ - while (__builtin_expect (textrels != NULL, 0)) - { - if (__mprotect (textrels->start, textrels->len, textrels->prot) < 0) - { - errstring = N_("cannot restore segment prot after reloc"); - goto call_error; - } - -#ifdef CLEAR_CACHE - CLEAR_CACHE (textrels->start, textrels->start + textrels->len); -#endif - - textrels = textrels->next; - } - - /* In case we can protect the data now that the relocations are - done, do it. */ - if (l->l_relro_size != 0) - _dl_protect_relro (l); -} - - -void internal_function -_dl_protect_relro (struct link_map *l) -{ - 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) - { - static const char errstring[] = N_("\ -cannot apply additional memory protection after relocation"); - _dl_signal_error (errno, l->l_name, NULL, errstring); - } -} - -void -internal_function __attribute_noinline__ -_dl_reloc_bad_type (struct link_map *map, unsigned int type, int plt) -{ -#define DIGIT(b) _itoa_lower_digits[(b) & 0xf]; - - /* XXX We cannot translate these messages. */ - static const char msg[2][32 -#if __ELF_NATIVE_CLASS == 64 - + 6 -#endif - ] = { "unexpected reloc type 0x", - "unexpected PLT reloc type 0x" }; - char msgbuf[sizeof (msg[0])]; - char *cp; - - cp = __stpcpy (msgbuf, msg[plt]); -#if __ELF_NATIVE_CLASS == 64 - if (__builtin_expect(type > 0xff, 0)) - { - *cp++ = DIGIT (type >> 28); - *cp++ = DIGIT (type >> 24); - *cp++ = DIGIT (type >> 20); - *cp++ = DIGIT (type >> 16); - *cp++ = DIGIT (type >> 12); - *cp++ = DIGIT (type >> 8); - } -#endif - *cp++ = DIGIT (type >> 4); - *cp++ = DIGIT (type); - *cp = '\0'; - - _dl_signal_error (0, map->l_name, NULL, msgbuf); -} diff --git a/elf/dl-runtime.c b/elf/dl-runtime.c deleted file mode 100644 index 7d1d240403..0000000000 --- a/elf/dl-runtime.c +++ /dev/null @@ -1,480 +0,0 @@ -/* On-demand PLT fixup for shared objects. - Copyright (C) 1995-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -#define IN_DL_RUNTIME 1 /* This can be tested in dl-machine.h. */ - -#include <alloca.h> -#include <stdlib.h> -#include <unistd.h> -#include <sys/param.h> -#include <ldsodefs.h> -#include <sysdep-cancel.h> -#include "dynamic-link.h" -#include <tls.h> -#include <dl-irel.h> - - -#if (!ELF_MACHINE_NO_RELA && !defined ELF_MACHINE_PLT_REL) \ - || ELF_MACHINE_NO_REL -# define PLTREL ElfW(Rela) -#else -# define PLTREL ElfW(Rel) -#endif - -/* The fixup functions might have need special attributes. If none - are provided define the macro as empty. */ -#ifndef ARCH_FIXUP_ATTRIBUTE -# define ARCH_FIXUP_ATTRIBUTE -#endif - -#ifndef reloc_offset -# define reloc_offset reloc_arg -# define reloc_index reloc_arg / sizeof (PLTREL) -#endif - - - -/* This function is called through a special trampoline from the PLT the - first time each PLT entry is called. We must perform the relocation - specified in the PLT of the given shared object, and return the resolved - function address to the trampoline, which will restart the original call - to that address. Future calls will bounce directly from the PLT to the - function. */ - -DL_FIXUP_VALUE_TYPE -attribute_hidden __attribute ((noinline)) ARCH_FIXUP_ATTRIBUTE -_dl_fixup ( -# ifdef ELF_MACHINE_RUNTIME_FIXUP_ARGS - ELF_MACHINE_RUNTIME_FIXUP_ARGS, -# endif - struct link_map *l, ElfW(Word) reloc_arg) -{ - const ElfW(Sym) *const symtab - = (const void *) D_PTR (l, l_info[DT_SYMTAB]); - const char *strtab = (const void *) D_PTR (l, l_info[DT_STRTAB]); - - const PLTREL *const reloc - = (const void *) (D_PTR (l, l_info[DT_JMPREL]) + reloc_offset); - const ElfW(Sym) *sym = &symtab[ELFW(R_SYM) (reloc->r_info)]; - void *const rel_addr = (void *)(l->l_addr + reloc->r_offset); - lookup_t result; - DL_FIXUP_VALUE_TYPE value; - - /* Sanity check that we're really looking at a PLT relocation. */ - assert (ELFW(R_TYPE)(reloc->r_info) == ELF_MACHINE_JMP_SLOT); - - /* Look up the target symbol. If the normal lookup rules are not - used don't look in the global scope. */ - if (__builtin_expect (ELFW(ST_VISIBILITY) (sym->st_other), 0) == 0) - { - const struct r_found_version *version = NULL; - - if (l->l_info[VERSYMIDX (DT_VERSYM)] != NULL) - { - const ElfW(Half) *vernum = - (const void *) D_PTR (l, l_info[VERSYMIDX (DT_VERSYM)]); - ElfW(Half) ndx = vernum[ELFW(R_SYM) (reloc->r_info)] & 0x7fff; - version = &l->l_versions[ndx]; - if (version->hash == 0) - version = NULL; - } - - /* We need to keep the scope around so do some locking. This is - not necessary for objects which cannot be unloaded or when - we are not using any threads (yet). */ - int flags = DL_LOOKUP_ADD_DEPENDENCY; - if (!RTLD_SINGLE_THREAD_P) - { - THREAD_GSCOPE_SET_FLAG (); - flags |= DL_LOOKUP_GSCOPE_LOCK; - } - -#ifdef RTLD_ENABLE_FOREIGN_CALL - RTLD_ENABLE_FOREIGN_CALL; -#endif - - result = _dl_lookup_symbol_x (strtab + sym->st_name, l, &sym, l->l_scope, - version, ELF_RTYPE_CLASS_PLT, flags, NULL); - - /* We are done with the global scope. */ - if (!RTLD_SINGLE_THREAD_P) - THREAD_GSCOPE_RESET_FLAG (); - -#ifdef RTLD_FINALIZE_FOREIGN_CALL - RTLD_FINALIZE_FOREIGN_CALL; -#endif - - /* Currently result contains the base load address (or link map) - of the object that defines sym. Now add in the symbol - offset. */ - value = DL_FIXUP_MAKE_VALUE (result, - sym ? (LOOKUP_VALUE_ADDRESS (result) - + sym->st_value) : 0); - } - else - { - /* We already found the symbol. The module (and therefore its load - address) is also known. */ - value = DL_FIXUP_MAKE_VALUE (l, l->l_addr + sym->st_value); - result = l; - } - - /* And now perhaps the relocation addend. */ - value = elf_machine_plt_value (l, reloc, value); - - if (sym != NULL - && __builtin_expect (ELFW(ST_TYPE) (sym->st_info) == STT_GNU_IFUNC, 0)) - value = elf_ifunc_invoke (DL_FIXUP_VALUE_ADDR (value)); - - /* Finally, fix up the plt itself. */ - if (__glibc_unlikely (GLRO(dl_bind_not))) - return value; - - return elf_machine_fixup_plt (l, result, reloc, rel_addr, value); -} - -#ifndef PROF -DL_FIXUP_VALUE_TYPE -__attribute ((noinline)) ARCH_FIXUP_ATTRIBUTE -_dl_profile_fixup ( -#ifdef ELF_MACHINE_RUNTIME_FIXUP_ARGS - ELF_MACHINE_RUNTIME_FIXUP_ARGS, -#endif - struct link_map *l, ElfW(Word) reloc_arg, - ElfW(Addr) retaddr, void *regs, long int *framesizep) -{ - void (*mcount_fct) (ElfW(Addr), ElfW(Addr)) = _dl_mcount; - - if (l->l_reloc_result == NULL) - { - /* BZ #14843: ELF_DYNAMIC_RELOCATE is called before l_reloc_result - is allocated. We will get here if ELF_DYNAMIC_RELOCATE calls a - resolver function to resolve an IRELATIVE relocation and that - resolver calls a function that is not yet resolved (lazy). For - example, the resolver in x86-64 libm.so calls __get_cpu_features - defined in libc.so. Skip audit and resolve the external function - in this case. */ - *framesizep = -1; - return _dl_fixup ( -# ifdef ELF_MACHINE_RUNTIME_FIXUP_ARGS -# ifndef ELF_MACHINE_RUNTIME_FIXUP_PARAMS -# error Please define ELF_MACHINE_RUNTIME_FIXUP_PARAMS. -# endif - ELF_MACHINE_RUNTIME_FIXUP_PARAMS, -# endif - l, reloc_arg); - } - - /* This is the address in the array where we store the result of previous - relocations. */ - struct reloc_result *reloc_result = &l->l_reloc_result[reloc_index]; - DL_FIXUP_VALUE_TYPE *resultp = &reloc_result->addr; - - DL_FIXUP_VALUE_TYPE value = *resultp; - if (DL_FIXUP_VALUE_CODE_ADDR (value) == 0) - { - /* This is the first time we have to relocate this object. */ - const ElfW(Sym) *const symtab - = (const void *) D_PTR (l, l_info[DT_SYMTAB]); - const char *strtab = (const char *) D_PTR (l, l_info[DT_STRTAB]); - - const PLTREL *const reloc - = (const void *) (D_PTR (l, l_info[DT_JMPREL]) + reloc_offset); - const ElfW(Sym) *refsym = &symtab[ELFW(R_SYM) (reloc->r_info)]; - const ElfW(Sym) *defsym = refsym; - lookup_t result; - - /* Sanity check that we're really looking at a PLT relocation. */ - assert (ELFW(R_TYPE)(reloc->r_info) == ELF_MACHINE_JMP_SLOT); - - /* Look up the target symbol. If the symbol is marked STV_PROTECTED - don't look in the global scope. */ - if (__builtin_expect (ELFW(ST_VISIBILITY) (refsym->st_other), 0) == 0) - { - const struct r_found_version *version = NULL; - - if (l->l_info[VERSYMIDX (DT_VERSYM)] != NULL) - { - const ElfW(Half) *vernum = - (const void *) D_PTR (l, l_info[VERSYMIDX (DT_VERSYM)]); - ElfW(Half) ndx = vernum[ELFW(R_SYM) (reloc->r_info)] & 0x7fff; - version = &l->l_versions[ndx]; - if (version->hash == 0) - version = NULL; - } - - /* We need to keep the scope around so do some locking. This is - not necessary for objects which cannot be unloaded or when - we are not using any threads (yet). */ - int flags = DL_LOOKUP_ADD_DEPENDENCY; - if (!RTLD_SINGLE_THREAD_P) - { - THREAD_GSCOPE_SET_FLAG (); - flags |= DL_LOOKUP_GSCOPE_LOCK; - } - - result = _dl_lookup_symbol_x (strtab + refsym->st_name, l, - &defsym, l->l_scope, version, - ELF_RTYPE_CLASS_PLT, flags, NULL); - - /* We are done with the global scope. */ - if (!RTLD_SINGLE_THREAD_P) - THREAD_GSCOPE_RESET_FLAG (); - - /* Currently result contains the base load address (or link map) - of the object that defines sym. Now add in the symbol - offset. */ - value = DL_FIXUP_MAKE_VALUE (result, - defsym != NULL - ? LOOKUP_VALUE_ADDRESS (result) - + defsym->st_value : 0); - - if (defsym != NULL - && __builtin_expect (ELFW(ST_TYPE) (defsym->st_info) - == STT_GNU_IFUNC, 0)) - value = elf_ifunc_invoke (DL_FIXUP_VALUE_ADDR (value)); - } - else - { - /* We already found the symbol. The module (and therefore its load - address) is also known. */ - value = DL_FIXUP_MAKE_VALUE (l, l->l_addr + refsym->st_value); - - if (__builtin_expect (ELFW(ST_TYPE) (refsym->st_info) - == STT_GNU_IFUNC, 0)) - value = elf_ifunc_invoke (DL_FIXUP_VALUE_ADDR (value)); - - result = l; - } - /* And now perhaps the relocation addend. */ - value = elf_machine_plt_value (l, reloc, value); - -#ifdef SHARED - /* 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 (defsym != NULL && GLRO(dl_naudit) > 0) - { - reloc_result->bound = result; - /* Compute index of the symbol entry in the symbol table of - the DSO with the definition. */ - reloc_result->boundndx = (defsym - - (ElfW(Sym) *) D_PTR (result, - l_info[DT_SYMTAB])); - - /* Determine whether any of the two participating DSOs is - interested in auditing. */ - if ((l->l_audit_any_plt | result->l_audit_any_plt) != 0) - { - unsigned int flags = 0; - struct audit_ifaces *afct = GLRO(dl_audit); - /* Synthesize a symbol record where the st_value field is - the result. */ - ElfW(Sym) sym = *defsym; - sym.st_value = DL_FIXUP_VALUE_ADDR (value); - - /* Keep track whether there is any interest in tracing - the call in the lower two bits. */ - assert (DL_NNS * 2 <= sizeof (reloc_result->flags) * 8); - assert ((LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT) == 3); - reloc_result->enterexit = LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT; - - const char *strtab2 = (const void *) D_PTR (result, - l_info[DT_STRTAB]); - - for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) - { - /* XXX Check whether both DSOs must request action or - only one */ - if ((l->l_audit[cnt].bindflags & LA_FLG_BINDFROM) != 0 - && (result->l_audit[cnt].bindflags & LA_FLG_BINDTO) != 0) - { - if (afct->symbind != NULL) - { - uintptr_t new_value - = afct->symbind (&sym, reloc_result->boundndx, - &l->l_audit[cnt].cookie, - &result->l_audit[cnt].cookie, - &flags, - strtab2 + defsym->st_name); - if (new_value != (uintptr_t) sym.st_value) - { - flags |= LA_SYMB_ALTVALUE; - sym.st_value = new_value; - } - } - - /* Remember the results for every audit library and - store a summary in the first two bits. */ - reloc_result->enterexit - &= flags & (LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT); - reloc_result->enterexit - |= ((flags & (LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT)) - << ((cnt + 1) * 2)); - } - else - /* If the bind flags say this auditor is not interested, - set the bits manually. */ - reloc_result->enterexit - |= ((LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT) - << ((cnt + 1) * 2)); - - afct = afct->next; - } - - reloc_result->flags = flags; - value = DL_FIXUP_ADDR_VALUE (sym.st_value); - } - else - /* Set all bits since this symbol binding is not interesting. */ - reloc_result->enterexit = (1u << DL_NNS) - 1; - } -#endif - - /* Store the result for later runs. */ - if (__glibc_likely (! GLRO(dl_bind_not))) - *resultp = value; - } - - /* By default we do not call the pltexit function. */ - long int framesize = -1; - -#ifdef SHARED - /* Auditing checkpoint: report the PLT entering and allow the - auditors to change the value. */ - if (DL_FIXUP_VALUE_CODE_ADDR (value) != 0 && GLRO(dl_naudit) > 0 - /* Don't do anything if no auditor wants to intercept this call. */ - && (reloc_result->enterexit & LA_SYMB_NOPLTENTER) == 0) - { - ElfW(Sym) *defsym = ((ElfW(Sym) *) D_PTR (reloc_result->bound, - l_info[DT_SYMTAB]) - + reloc_result->boundndx); - - /* Set up the sym parameter. */ - ElfW(Sym) sym = *defsym; - sym.st_value = DL_FIXUP_VALUE_ADDR (value); - - /* Get the symbol name. */ - const char *strtab = (const void *) D_PTR (reloc_result->bound, - l_info[DT_STRTAB]); - const char *symname = strtab + sym.st_name; - - /* Keep track of overwritten addresses. */ - unsigned int flags = reloc_result->flags; - - struct audit_ifaces *afct = GLRO(dl_audit); - for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) - { - if (afct->ARCH_LA_PLTENTER != NULL - && (reloc_result->enterexit - & (LA_SYMB_NOPLTENTER << (2 * (cnt + 1)))) == 0) - { - long int new_framesize = -1; - uintptr_t new_value - = afct->ARCH_LA_PLTENTER (&sym, reloc_result->boundndx, - &l->l_audit[cnt].cookie, - &reloc_result->bound->l_audit[cnt].cookie, - regs, &flags, symname, - &new_framesize); - if (new_value != (uintptr_t) sym.st_value) - { - flags |= LA_SYMB_ALTVALUE; - sym.st_value = new_value; - } - - /* Remember the results for every audit library and - store a summary in the first two bits. */ - reloc_result->enterexit - |= ((flags & (LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT)) - << (2 * (cnt + 1))); - - if ((reloc_result->enterexit & (LA_SYMB_NOPLTEXIT - << (2 * (cnt + 1)))) - == 0 && new_framesize != -1 && framesize != -2) - { - /* If this is the first call providing information, - use it. */ - if (framesize == -1) - framesize = new_framesize; - /* If two pltenter calls provide conflicting information, - use the larger value. */ - else if (new_framesize != framesize) - framesize = MAX (new_framesize, framesize); - } - } - - afct = afct->next; - } - - value = DL_FIXUP_ADDR_VALUE (sym.st_value); - } -#endif - - /* Store the frame size information. */ - *framesizep = framesize; - - (*mcount_fct) (retaddr, DL_FIXUP_VALUE_CODE_ADDR (value)); - - return value; -} - -#endif /* PROF */ - - -#include <stdio.h> -void -ARCH_FIXUP_ATTRIBUTE -_dl_call_pltexit (struct link_map *l, ElfW(Word) reloc_arg, - const void *inregs, void *outregs) -{ -#ifdef SHARED - /* This is the address in the array where we store the result of previous - relocations. */ - // XXX Maybe the bound information must be stored on the stack since - // XXX with bind_not a new value could have been stored in the meantime. - struct reloc_result *reloc_result = &l->l_reloc_result[reloc_index]; - ElfW(Sym) *defsym = ((ElfW(Sym) *) D_PTR (reloc_result->bound, - l_info[DT_SYMTAB]) - + reloc_result->boundndx); - - /* Set up the sym parameter. */ - ElfW(Sym) sym = *defsym; - sym.st_value = DL_FIXUP_VALUE_ADDR (reloc_result->addr); - - /* Get the symbol name. */ - const char *strtab = (const void *) D_PTR (reloc_result->bound, - l_info[DT_STRTAB]); - const char *symname = strtab + sym.st_name; - - struct audit_ifaces *afct = GLRO(dl_audit); - for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) - { - if (afct->ARCH_LA_PLTEXIT != NULL - && (reloc_result->enterexit - & (LA_SYMB_NOPLTEXIT >> (2 * cnt))) == 0) - { - afct->ARCH_LA_PLTEXIT (&sym, reloc_result->boundndx, - &l->l_audit[cnt].cookie, - &reloc_result->bound->l_audit[cnt].cookie, - inregs, outregs, symname); - } - - afct = afct->next; - } -#endif -} diff --git a/elf/dl-sbrk.c b/elf/dl-sbrk.c deleted file mode 100644 index 4713a92694..0000000000 --- a/elf/dl-sbrk.c +++ /dev/null @@ -1,5 +0,0 @@ -/* We can use the normal code but we also know the __curbrk is not exported - from ld.so. */ -extern void *__curbrk attribute_hidden; - -#include <sbrk.c> diff --git a/elf/dl-scope.c b/elf/dl-scope.c deleted file mode 100644 index bb924afa8f..0000000000 --- a/elf/dl-scope.c +++ /dev/null @@ -1,57 +0,0 @@ -/* Memory handling for the scope data structures. - Copyright (C) 2009-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -#include <stdlib.h> -#include <ldsodefs.h> -#include <sysdep-cancel.h> - - -int -_dl_scope_free (void *old) -{ - struct dl_scope_free_list *fsl; -#define DL_SCOPE_FREE_LIST_SIZE (sizeof (fsl->list) / sizeof (fsl->list[0])) - - if (RTLD_SINGLE_THREAD_P) - free (old); - else if ((fsl = GL(dl_scope_free_list)) == NULL) - { - GL(dl_scope_free_list) = fsl = malloc (sizeof (*fsl)); - if (fsl == NULL) - { - THREAD_GSCOPE_WAIT (); - free (old); - return 1; - } - else - { - fsl->list[0] = old; - fsl->count = 1; - } - } - else if (fsl->count < DL_SCOPE_FREE_LIST_SIZE) - fsl->list[fsl->count++] = old; - else - { - THREAD_GSCOPE_WAIT (); - while (fsl->count > 0) - free (fsl->list[--fsl->count]); - return 1; - } - return 0; -} diff --git a/elf/dl-support.c b/elf/dl-support.c deleted file mode 100644 index c22be854f4..0000000000 --- a/elf/dl-support.c +++ /dev/null @@ -1,389 +0,0 @@ -/* Support for dynamic linking code in static libc. - Copyright (C) 1996-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -/* This file defines some things that for the dynamic linker are defined in - rtld.c and dl-sysdep.c in ways appropriate to bootstrap dynamic linking. */ - -#include <errno.h> -#include <libintl.h> -#include <stdlib.h> -#include <unistd.h> -#include <sys/param.h> -#include <stdint.h> -#include <ldsodefs.h> -#include <dl-machine.h> -#include <libc-lock.h> -#include <dl-cache.h> -#include <dl-librecon.h> -#include <dl-procinfo.h> -#include <unsecvars.h> -#include <hp-timing.h> -#include <stackinfo.h> - -extern char *__progname; -char **_dl_argv = &__progname; /* This is checked for some error messages. */ - -/* Name of the architecture. */ -const char *_dl_platform; -size_t _dl_platformlen; - -int _dl_debug_mask; -int _dl_lazy; -ElfW(Addr) _dl_use_load_bias = -2; -int _dl_dynamic_weak; - -/* If nonzero print warnings about problematic situations. */ -int _dl_verbose; - -/* We never do profiling. */ -const char *_dl_profile; -const char *_dl_profile_output; - -/* Names of shared object for which the RUNPATHs and RPATHs should be - ignored. */ -const char *_dl_inhibit_rpath; - -/* The map for the object we will profile. */ -struct link_map *_dl_profile_map; - -/* This is the address of the last stack address ever used. */ -void *__libc_stack_end; - -/* Path where the binary is found. */ -const char *_dl_origin_path; - -/* Nonzero if runtime lookup should not update the .got/.plt. */ -int _dl_bind_not; - -/* A dummy link map for the executable, used by dlopen to access the global - scope. We don't export any symbols ourselves, so this can be minimal. */ -static struct link_map _dl_main_map = - { - .l_name = (char *) "", - .l_real = &_dl_main_map, - .l_ns = LM_ID_BASE, - .l_libname = &(struct libname_list) { .name = "", .dont_free = 1 }, - .l_searchlist = - { - .r_list = &(struct link_map *) { &_dl_main_map }, - .r_nlist = 1, - }, - .l_symbolic_searchlist = { .r_list = &(struct link_map *) { NULL } }, - .l_type = lt_executable, - .l_scope_mem = { &_dl_main_map.l_searchlist }, - .l_scope_max = (sizeof (_dl_main_map.l_scope_mem) - / sizeof (_dl_main_map.l_scope_mem[0])), - .l_scope = _dl_main_map.l_scope_mem, - .l_local_scope = { &_dl_main_map.l_searchlist }, - .l_used = 1, - .l_tls_offset = NO_TLS_OFFSET, - .l_serial = 1, - }; - -/* Namespace information. */ -struct link_namespaces _dl_ns[DL_NNS] = - { - [LM_ID_BASE] = - { - ._ns_loaded = &_dl_main_map, - ._ns_nloaded = 1, - ._ns_main_searchlist = &_dl_main_map.l_searchlist, - } - }; -size_t _dl_nns = 1; - -/* Incremented whenever something may have been added to dl_loaded. */ -unsigned long long _dl_load_adds = 1; - -/* Fake scope of the main application. */ -struct r_scope_elem _dl_initial_searchlist = - { - .r_list = &(struct link_map *) { &_dl_main_map }, - .r_nlist = 1, - }; - -#ifndef HAVE_INLINED_SYSCALLS -/* Nonzero during startup. */ -int _dl_starting_up = 1; -#endif - -/* Random data provided by the kernel. */ -void *_dl_random; - -/* Get architecture specific initializer. */ -#include <dl-procinfo.c> - -/* Initial value of the CPU clock. */ -#ifndef HP_TIMING_NONAVAIL -hp_timing_t _dl_cpuclock_offset; -#endif - -void (*_dl_init_static_tls) (struct link_map *) = &_dl_nothread_init_static_tls; - -size_t _dl_pagesize = EXEC_PAGESIZE; - -int _dl_inhibit_cache; - -unsigned int _dl_osversion; - -/* All known directories in sorted order. */ -struct r_search_path_elem *_dl_all_dirs; - -/* All directories after startup. */ -struct r_search_path_elem *_dl_init_all_dirs; - -/* The object to be initialized first. */ -struct link_map *_dl_initfirst; - -/* Descriptor to write debug messages to. */ -int _dl_debug_fd = STDERR_FILENO; - -int _dl_correct_cache_id = _DL_CACHE_DEFAULT_ID; - -ElfW(auxv_t) *_dl_auxv; -const ElfW(Phdr) *_dl_phdr; -size_t _dl_phnum; -uint64_t _dl_hwcap __attribute__ ((nocommon)); -uint64_t _dl_hwcap2 __attribute__ ((nocommon)); - -/* The value of the FPU control word the kernel will preset in hardware. */ -fpu_control_t _dl_fpu_control = _FPU_DEFAULT; - -#if !HAVE_TUNABLES -/* This is not initialized to HWCAP_IMPORTANT, matching the definition - of _dl_important_hwcaps, below, where no hwcap strings are ever - used. This mask is still used to mediate the lookups in the cache - file. Since there is no way to set this nonzero (we don't grok the - LD_HWCAP_MASK environment variable here), there is no real point in - setting _dl_hwcap nonzero below, but we do anyway. */ -uint64_t _dl_hwcap_mask __attribute__ ((nocommon)); -#endif - -/* Prevailing state of the stack. Generally this includes PF_X, indicating it's - * executable but this isn't true for all platforms. */ -ElfW(Word) _dl_stack_flags = DEFAULT_STACK_PERMS; - -/* If loading a shared object requires that we make the stack executable - when it was not, we do it by calling this function. - It returns an errno code or zero on success. */ -int (*_dl_make_stack_executable_hook) (void **) internal_function - = _dl_make_stack_executable; - - -/* Function in libpthread to wait for termination of lookups. */ -void (*_dl_wait_lookup_done) (void); - -struct dl_scope_free_list *_dl_scope_free_list; - -#ifdef NEED_DL_SYSINFO -/* Needed for improved syscall handling on at least x86/Linux. */ -uintptr_t _dl_sysinfo = DL_SYSINFO_DEFAULT; -#endif -#ifdef NEED_DL_SYSINFO_DSO -/* Address of the ELF headers in the vsyscall page. */ -const ElfW(Ehdr) *_dl_sysinfo_dso; - -struct link_map *_dl_sysinfo_map; - -# include "get-dynamic-info.h" -#endif -#include "setup-vdso.h" - -/* During the program run we must not modify the global data of - loaded shared object simultanously in two threads. Therefore we - protect `_dl_open' and `_dl_close' in dl-close.c. - - This must be a recursive lock since the initializer function of - the loaded object might as well require a call to this function. - At this time it is not anymore a problem to modify the tables. */ -__rtld_lock_define_initialized_recursive (, _dl_load_lock) -/* This lock is used to keep __dl_iterate_phdr from inspecting the - list of loaded objects while an object is added to or removed from - that list. */ -__rtld_lock_define_initialized_recursive (, _dl_load_write_lock) - - -#ifdef HAVE_AUX_VECTOR -int _dl_clktck; - -void -internal_function -_dl_aux_init (ElfW(auxv_t) *av) -{ - int seen = 0; - uid_t uid = 0; - gid_t gid = 0; - - _dl_auxv = av; - for (; av->a_type != AT_NULL; ++av) - switch (av->a_type) - { - case AT_PAGESZ: - if (av->a_un.a_val != 0) - GLRO(dl_pagesize) = av->a_un.a_val; - break; - case AT_CLKTCK: - GLRO(dl_clktck) = av->a_un.a_val; - break; - case AT_PHDR: - GL(dl_phdr) = (const void *) av->a_un.a_val; - break; - case AT_PHNUM: - GL(dl_phnum) = av->a_un.a_val; - break; - case AT_PLATFORM: - GLRO(dl_platform) = (void *) av->a_un.a_val; - break; - case AT_HWCAP: - GLRO(dl_hwcap) = (unsigned long int) av->a_un.a_val; - break; - case AT_HWCAP2: - GLRO(dl_hwcap2) = (unsigned long int) av->a_un.a_val; - break; - case AT_FPUCW: - GLRO(dl_fpu_control) = av->a_un.a_val; - break; -#ifdef NEED_DL_SYSINFO - case AT_SYSINFO: - GL(dl_sysinfo) = av->a_un.a_val; - break; -#endif -#ifdef NEED_DL_SYSINFO_DSO - case AT_SYSINFO_EHDR: - GL(dl_sysinfo_dso) = (void *) av->a_un.a_val; - break; -#endif - case AT_UID: - uid ^= av->a_un.a_val; - seen |= 1; - break; - case AT_EUID: - uid ^= av->a_un.a_val; - seen |= 2; - break; - case AT_GID: - gid ^= av->a_un.a_val; - seen |= 4; - break; - case AT_EGID: - gid ^= av->a_un.a_val; - seen |= 8; - break; - case AT_SECURE: - seen = -1; - __libc_enable_secure = av->a_un.a_val; - __libc_enable_secure_decided = 1; - break; - case AT_RANDOM: - _dl_random = (void *) av->a_un.a_val; - break; -# ifdef DL_PLATFORM_AUXV - DL_PLATFORM_AUXV -# endif - } - if (seen == 0xf) - { - __libc_enable_secure = uid != 0 || gid != 0; - __libc_enable_secure_decided = 1; - } -} -#endif - - -void -internal_function -_dl_non_dynamic_init (void) -{ - _dl_main_map.l_origin = _dl_get_origin (); - _dl_main_map.l_phdr = GL(dl_phdr); - _dl_main_map.l_phnum = GL(dl_phnum); - - if (HP_SMALL_TIMING_AVAIL) - HP_TIMING_NOW (_dl_cpuclock_offset); - - _dl_verbose = *(getenv ("LD_WARN") ?: "") == '\0' ? 0 : 1; - - /* Set up the data structures for the system-supplied DSO early, - so they can influence _dl_init_paths. */ - setup_vdso (NULL, NULL); - - /* Initialize the data structures for the search paths for shared - objects. */ - _dl_init_paths (getenv ("LD_LIBRARY_PATH")); - - /* Remember the last search directory added at startup. */ - _dl_init_all_dirs = GL(dl_all_dirs); - - _dl_lazy = *(getenv ("LD_BIND_NOW") ?: "") == '\0'; - - _dl_bind_not = *(getenv ("LD_BIND_NOT") ?: "") != '\0'; - - _dl_dynamic_weak = *(getenv ("LD_DYNAMIC_WEAK") ?: "") == '\0'; - - _dl_profile_output = getenv ("LD_PROFILE_OUTPUT"); - if (_dl_profile_output == NULL || _dl_profile_output[0] == '\0') - _dl_profile_output - = &"/var/tmp\0/var/profile"[__libc_enable_secure ? 9 : 0]; - - if (__libc_enable_secure) - { - static const char unsecure_envvars[] = - UNSECURE_ENVVARS -#ifdef EXTRA_UNSECURE_ENVVARS - EXTRA_UNSECURE_ENVVARS -#endif - ; - const char *cp = unsecure_envvars; - - while (cp < unsecure_envvars + sizeof (unsecure_envvars)) - { - __unsetenv (cp); - cp = (const char *) __rawmemchr (cp, '\0') + 1; - } - -#if !HAVE_TUNABLES - if (__access ("/etc/suid-debug", F_OK) != 0) - __unsetenv ("MALLOC_CHECK_"); -#endif - } - -#ifdef DL_PLATFORM_INIT - DL_PLATFORM_INIT; -#endif - -#ifdef DL_OSVERSION_INIT - DL_OSVERSION_INIT; -#endif - - /* Now determine the length of the platform string. */ - if (_dl_platform != NULL) - _dl_platformlen = strlen (_dl_platform); - - /* Scan for a program header telling us the stack is nonexecutable. */ - if (_dl_phdr != NULL) - for (uint_fast16_t i = 0; i < _dl_phnum; ++i) - if (_dl_phdr[i].p_type == PT_GNU_STACK) - { - _dl_stack_flags = _dl_phdr[i].p_flags; - break; - } -} - -#ifdef DL_SYSINFO_IMPLEMENTATION -DL_SYSINFO_IMPLEMENTATION -#endif diff --git a/elf/dl-sym.c b/elf/dl-sym.c deleted file mode 100644 index 7cd6e97643..0000000000 --- a/elf/dl-sym.c +++ /dev/null @@ -1,274 +0,0 @@ -/* Look up a symbol in a shared object loaded by `dlopen'. - Copyright (C) 1999-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -#include <assert.h> -#include <stddef.h> -#include <setjmp.h> -#include <stdlib.h> -#include <libintl.h> - -#include <dlfcn.h> -#include <ldsodefs.h> -#include <dl-hash.h> -#include <sysdep-cancel.h> -#include <dl-tls.h> -#include <dl-irel.h> - - -#ifdef SHARED -/* Systems which do not have tls_index also probably have to define - DONT_USE_TLS_INDEX. */ - -# ifndef __TLS_GET_ADDR -# define __TLS_GET_ADDR __tls_get_addr -# endif - -/* Return the symbol address given the map of the module it is in and - the symbol record. This is used in dl-sym.c. */ -static void * -internal_function -_dl_tls_symaddr (struct link_map *map, const ElfW(Sym) *ref) -{ -# ifndef DONT_USE_TLS_INDEX - tls_index tmp = - { - .ti_module = map->l_tls_modid, - .ti_offset = ref->st_value - }; - - return __TLS_GET_ADDR (&tmp); -# else - return __TLS_GET_ADDR (map->l_tls_modid, ref->st_value); -# endif -} -#endif - - -struct call_dl_lookup_args -{ - /* Arguments to do_dlsym. */ - struct link_map *map; - const char *name; - struct r_found_version *vers; - int flags; - - /* Return values of do_dlsym. */ - lookup_t loadbase; - const ElfW(Sym) **refp; -}; - -static void -call_dl_lookup (void *ptr) -{ - struct call_dl_lookup_args *args = (struct call_dl_lookup_args *) ptr; - args->map = GLRO(dl_lookup_symbol_x) (args->name, args->map, args->refp, - args->map->l_scope, args->vers, 0, - args->flags, NULL); -} - - -static void * -internal_function -do_sym (void *handle, const char *name, void *who, - struct r_found_version *vers, int flags) -{ - const ElfW(Sym) *ref = NULL; - lookup_t result; - ElfW(Addr) caller = (ElfW(Addr)) who; - - struct link_map *l = _dl_find_dso_for_object (caller); - /* If the address is not recognized the call comes from the main - program (we hope). */ - struct link_map *match = l ? l : GL(dl_ns)[LM_ID_BASE]._ns_loaded; - - if (handle == RTLD_DEFAULT) - { - /* Search the global scope. We have the simple case where - we look up in the scope of an object which was part of - the initial binary. And then the more complex part - where the object is dynamically loaded and the scope - array can change. */ - if (RTLD_SINGLE_THREAD_P) - result = GLRO(dl_lookup_symbol_x) (name, match, &ref, - match->l_scope, vers, 0, - flags | DL_LOOKUP_ADD_DEPENDENCY, - NULL); - else - { - struct call_dl_lookup_args args; - args.name = name; - args.map = match; - args.vers = vers; - args.flags - = flags | DL_LOOKUP_ADD_DEPENDENCY | DL_LOOKUP_GSCOPE_LOCK; - args.refp = &ref; - - THREAD_GSCOPE_SET_FLAG (); - - const char *objname; - const char *errstring = NULL; - bool malloced; - int err = _dl_catch_error (&objname, &errstring, &malloced, - call_dl_lookup, &args); - - THREAD_GSCOPE_RESET_FLAG (); - - if (__glibc_unlikely (errstring != NULL)) - { - /* The lookup was unsuccessful. Rethrow the error. */ - char *errstring_dup = strdupa (errstring); - char *objname_dup = strdupa (objname); - if (malloced) - free ((char *) errstring); - - _dl_signal_error (err, objname_dup, NULL, errstring_dup); - /* NOTREACHED */ - } - - result = args.map; - } - } - else if (handle == RTLD_NEXT) - { - if (__glibc_unlikely (match == GL(dl_ns)[LM_ID_BASE]._ns_loaded)) - { - if (match == NULL - || caller < match->l_map_start - || caller >= match->l_map_end) - _dl_signal_error (0, NULL, NULL, N_("\ -RTLD_NEXT used in code not dynamically loaded")); - } - - struct link_map *l = match; - while (l->l_loader != NULL) - l = l->l_loader; - - result = GLRO(dl_lookup_symbol_x) (name, match, &ref, l->l_local_scope, - vers, 0, 0, match); - } - else - { - /* Search the scope of the given object. */ - struct link_map *map = handle; - result = GLRO(dl_lookup_symbol_x) (name, map, &ref, map->l_local_scope, - vers, 0, flags, NULL); - } - - if (ref != NULL) - { - void *value; - -#ifdef SHARED - if (ELFW(ST_TYPE) (ref->st_info) == STT_TLS) - /* The found symbol is a thread-local storage variable. - Return the address for to the current thread. */ - value = _dl_tls_symaddr (result, ref); - else -#endif - value = DL_SYMBOL_ADDRESS (result, ref); - - /* Resolve indirect function address. */ - 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); - fixup = elf_ifunc_invoke (DL_FIXUP_VALUE_ADDR (fixup)); - value = (void *) DL_FIXUP_VALUE_CODE_ADDR (fixup); - } - -#ifdef SHARED - /* 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 (__glibc_unlikely (GLRO(dl_naudit) > 0)) - { - const char *strtab = (const char *) D_PTR (result, - l_info[DT_STRTAB]); - /* Compute index of the symbol entry in the symbol table of - the DSO with the definition. */ - unsigned int ndx = (ref - (ElfW(Sym) *) D_PTR (result, - l_info[DT_SYMTAB])); - - if ((match->l_audit_any_plt | result->l_audit_any_plt) != 0) - { - unsigned int altvalue = 0; - struct audit_ifaces *afct = GLRO(dl_audit); - /* Synthesize a symbol record where the st_value field is - the result. */ - ElfW(Sym) sym = *ref; - sym.st_value = (ElfW(Addr)) value; - - for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) - { - if (afct->symbind != NULL - && ((match->l_audit[cnt].bindflags & LA_FLG_BINDFROM) - != 0 - || ((result->l_audit[cnt].bindflags & LA_FLG_BINDTO) - != 0))) - { - unsigned int flags = altvalue | LA_SYMB_DLSYM; - uintptr_t new_value - = afct->symbind (&sym, ndx, - &match->l_audit[cnt].cookie, - &result->l_audit[cnt].cookie, - &flags, strtab + ref->st_name); - if (new_value != (uintptr_t) sym.st_value) - { - altvalue = LA_SYMB_ALTVALUE; - sym.st_value = new_value; - } - } - - afct = afct->next; - } - - value = (void *) sym.st_value; - } - } -#endif - - return value; - } - - return NULL; -} - - -void * -internal_function -_dl_vsym (void *handle, const char *name, const char *version, void *who) -{ - struct r_found_version vers; - - /* Compute hash value to the version string. */ - vers.name = version; - vers.hidden = 1; - vers.hash = _dl_elf_hash (version); - /* We don't have a specific file where the symbol can be found. */ - vers.filename = NULL; - - return do_sym (handle, name, who, &vers, 0); -} - - -void * -internal_function -_dl_sym (void *handle, const char *name, void *who) -{ - return do_sym (handle, name, who, NULL, DL_LOOKUP_RETURN_NEWEST); -} diff --git a/elf/dl-symaddr.c b/elf/dl-symaddr.c deleted file mode 100644 index 5caed4ba21..0000000000 --- a/elf/dl-symaddr.c +++ /dev/null @@ -1,33 +0,0 @@ -/* Get the symbol address. Generic version. - Copyright (C) 1999-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -#include <ldsodefs.h> -#include <dl-fptr.h> - -void * -_dl_symbol_address (struct link_map *map, const ElfW(Sym) *ref) -{ - ElfW(Addr) value = (map ? map->l_addr : 0) + ref->st_value; - - /* Return the pointer to function descriptor. */ - if (ELFW(ST_TYPE) (ref->st_info) == STT_FUNC) - return (void *) _dl_make_fptr (map, ref, value); - else - return (void *) value; -} -rtld_hidden_def (_dl_symbol_address) diff --git a/elf/dl-sysdep-open.h b/elf/dl-sysdep-open.h deleted file mode 100644 index 91851848b3..0000000000 --- a/elf/dl-sysdep-open.h +++ /dev/null @@ -1,45 +0,0 @@ -/* System-specific call to open a shared object by name. Stub version. - Copyright (C) 2015-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -#ifndef _DL_SYSDEP_OPEN_H -#define _DL_SYSDEP_OPEN_H 1 - -#include <assert.h> -#include <stddef.h> - -/* NAME is a name without slashes, as it appears in a DT_NEEDED entry - or a dlopen call's argument or suchlike. NAMELEN is (strlen (NAME) + 1). - - Find NAME in an OS-dependent fashion, and return its "real" name. - Optionally fill in *FD with a file descriptor open on that file (or - else leave its initial value of -1). The return value is a new - malloc'd string, which will be free'd by the caller. If NAME is - resolved to an actual file that can be opened, then the return - value should name that file (and if *FD was not set, then a normal - __open call on that string will be made). If *FD was set by some - other means than a normal open and there is no "real" name to use, - then __strdup (NAME) is fine (modulo error checking). */ - -static inline char * -_dl_sysdep_open_object (const char *name, size_t namelen, int *fd) -{ - assert (*fd == -1); - return NULL; -} - -#endif /* dl-sysdep-open.h */ diff --git a/elf/dl-sysdep.c b/elf/dl-sysdep.c deleted file mode 100644 index 4053ff3c07..0000000000 --- a/elf/dl-sysdep.c +++ /dev/null @@ -1,360 +0,0 @@ -/* Operating system support for run-time dynamic linker. Generic Unix version. - Copyright (C) 1995-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -/* We conditionalize the whole of this file rather than simply eliding it - from the static build, because other sysdeps/ versions of this file - might define things needed by a static build. */ - -#ifdef SHARED - -#include <assert.h> -#include <elf.h> -#include <errno.h> -#include <fcntl.h> -#include <libintl.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/mman.h> -#include <ldsodefs.h> -#include <_itoa.h> -#include <fpu_control.h> - -#include <entry.h> -#include <dl-machine.h> -#include <dl-procinfo.h> -#include <dl-osinfo.h> -#include <hp-timing.h> -#include <tls.h> - -#include <dl-tunables.h> - -extern char **_environ attribute_hidden; -extern char _end[] attribute_hidden; - -/* Protect SUID program against misuse of file descriptors. */ -extern void __libc_check_standard_fds (void); - -#ifdef NEED_DL_BASE_ADDR -ElfW(Addr) _dl_base_addr; -#endif -int __libc_enable_secure attribute_relro = 0; -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. */ -void *__libc_stack_end attribute_relro = NULL; -rtld_hidden_data_def(__libc_stack_end) -void *_dl_random attribute_relro = NULL; - -#ifndef DL_FIND_ARG_COMPONENTS -# define DL_FIND_ARG_COMPONENTS(cookie, argc, argv, envp, auxp) \ - do { \ - void **_tmp; \ - (argc) = *(long int *) cookie; \ - (argv) = (char **) ((long int *) cookie + 1); \ - (envp) = (argv) + (argc) + 1; \ - for (_tmp = (void **) (envp); *_tmp; ++_tmp) \ - continue; \ - (auxp) = (void *) ++_tmp; \ - } while (0) -#endif - -#ifndef DL_STACK_END -# define DL_STACK_END(cookie) ((void *) (cookie)) -#endif - -ElfW(Addr) -_dl_sysdep_start (void **start_argptr, - void (*dl_main) (const ElfW(Phdr) *phdr, ElfW(Word) phnum, - ElfW(Addr) *user_entry, ElfW(auxv_t) *auxv)) -{ - const ElfW(Phdr) *phdr = NULL; - ElfW(Word) phnum = 0; - ElfW(Addr) user_entry; - ElfW(auxv_t) *av; -#ifdef HAVE_AUX_SECURE -# define set_seen(tag) (tag) /* Evaluate for the side effects. */ -# define set_seen_secure() ((void) 0) -#else - uid_t uid = 0; - gid_t gid = 0; - unsigned int seen = 0; -# define set_seen_secure() (seen = -1) -# ifdef HAVE_AUX_XID -# define set_seen(tag) (tag) /* Evaluate for the side effects. */ -# else -# define M(type) (1 << (type)) -# define set_seen(tag) seen |= M ((tag)->a_type) -# endif -#endif -#ifdef NEED_DL_SYSINFO - uintptr_t new_sysinfo = 0; -#endif - - __libc_stack_end = DL_STACK_END (start_argptr); - DL_FIND_ARG_COMPONENTS (start_argptr, _dl_argc, _dl_argv, _environ, - GLRO(dl_auxv)); - - user_entry = (ElfW(Addr)) ENTRY_POINT; - GLRO(dl_platform) = NULL; /* Default to nothing known about the platform. */ - - for (av = GLRO(dl_auxv); av->a_type != AT_NULL; set_seen (av++)) - switch (av->a_type) - { - case AT_PHDR: - phdr = (void *) av->a_un.a_val; - break; - case AT_PHNUM: - phnum = av->a_un.a_val; - break; - case AT_PAGESZ: - GLRO(dl_pagesize) = av->a_un.a_val; - break; - case AT_ENTRY: - user_entry = av->a_un.a_val; - break; -#ifdef NEED_DL_BASE_ADDR - case AT_BASE: - _dl_base_addr = av->a_un.a_val; - break; -#endif -#ifndef HAVE_AUX_SECURE - case AT_UID: - case AT_EUID: - uid ^= av->a_un.a_val; - break; - case AT_GID: - case AT_EGID: - gid ^= av->a_un.a_val; - break; -#endif - case AT_SECURE: -#ifndef HAVE_AUX_SECURE - seen = -1; -#endif - __libc_enable_secure = av->a_un.a_val; - break; - case AT_PLATFORM: - GLRO(dl_platform) = (void *) av->a_un.a_val; - break; - case AT_HWCAP: - GLRO(dl_hwcap) = (unsigned long int) av->a_un.a_val; - break; - case AT_HWCAP2: - GLRO(dl_hwcap2) = (unsigned long int) av->a_un.a_val; - break; - case AT_CLKTCK: - GLRO(dl_clktck) = av->a_un.a_val; - break; - case AT_FPUCW: - GLRO(dl_fpu_control) = av->a_un.a_val; - break; -#ifdef NEED_DL_SYSINFO - case AT_SYSINFO: - new_sysinfo = av->a_un.a_val; - break; -#endif -#ifdef NEED_DL_SYSINFO_DSO - case AT_SYSINFO_EHDR: - GLRO(dl_sysinfo_dso) = (void *) av->a_un.a_val; - break; -#endif - case AT_RANDOM: - _dl_random = (void *) av->a_un.a_val; - break; -#ifdef DL_PLATFORM_AUXV - DL_PLATFORM_AUXV -#endif - } - -#ifndef HAVE_AUX_SECURE - if (seen != -1) - { - /* Fill in the values we have not gotten from the kernel through the - auxiliary vector. */ -# ifndef HAVE_AUX_XID -# define SEE(UID, var, uid) \ - if ((seen & M (AT_##UID)) == 0) var ^= __get##uid () - SEE (UID, uid, uid); - SEE (EUID, uid, euid); - SEE (GID, gid, gid); - SEE (EGID, gid, egid); -# endif - - /* If one of the two pairs of IDs does not match this is a setuid - or setgid run. */ - __libc_enable_secure = uid | gid; - } -#endif - -#ifndef HAVE_AUX_PAGESIZE - if (GLRO(dl_pagesize) == 0) - GLRO(dl_pagesize) = __getpagesize (); -#endif - -#ifdef NEED_DL_SYSINFO - if (new_sysinfo != 0) - { -# ifdef NEED_DL_SYSINFO_DSO - /* Only set the sysinfo value if we also have the vsyscall DSO. */ - if (GLRO(dl_sysinfo_dso) != 0) -# endif - GLRO(dl_sysinfo) = new_sysinfo; - } -#endif - - __tunables_init (_environ); - -#ifdef DL_SYSDEP_INIT - DL_SYSDEP_INIT; -#endif - -#ifdef DL_PLATFORM_INIT - DL_PLATFORM_INIT; -#endif - - /* Determine the length of the platform name. */ - if (GLRO(dl_platform) != NULL) - GLRO(dl_platformlen) = strlen (GLRO(dl_platform)); - - if (__sbrk (0) == _end) - /* The dynamic linker was run as a program, and so the initial break - starts just after our bss, at &_end. The malloc in dl-minimal.c - will consume the rest of this page, so tell the kernel to move the - break up that far. When the user program examines its break, it - will see this new value and not clobber our data. */ - __sbrk (GLRO(dl_pagesize) - - ((_end - (char *) 0) & (GLRO(dl_pagesize) - 1))); - - /* 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 (__libc_enable_secure, 0)) - __libc_check_standard_fds (); - - (*dl_main) (phdr, phnum, &user_entry, GLRO(dl_auxv)); - return user_entry; -} - -void -internal_function -_dl_sysdep_start_cleanup (void) -{ -} - -void -internal_function -_dl_show_auxv (void) -{ - char buf[64]; - ElfW(auxv_t) *av; - - /* Terminate string. */ - buf[63] = '\0'; - - /* The following code assumes that the AT_* values are encoded - starting from 0 with AT_NULL, 1 for AT_IGNORE, and all other values - close by (otherwise the array will be too large). In case we have - to support a platform where these requirements are not fulfilled - some alternative implementation has to be used. */ - for (av = GLRO(dl_auxv); av->a_type != AT_NULL; ++av) - { - static const struct - { - const char label[17]; - enum { unknown = 0, dec, hex, str, ignore } form : 8; - } auxvars[] = - { - [AT_EXECFD - 2] = { "EXECFD: ", dec }, - [AT_EXECFN - 2] = { "EXECFN: ", str }, - [AT_PHDR - 2] = { "PHDR: 0x", hex }, - [AT_PHENT - 2] = { "PHENT: ", dec }, - [AT_PHNUM - 2] = { "PHNUM: ", dec }, - [AT_PAGESZ - 2] = { "PAGESZ: ", dec }, - [AT_BASE - 2] = { "BASE: 0x", hex }, - [AT_FLAGS - 2] = { "FLAGS: 0x", hex }, - [AT_ENTRY - 2] = { "ENTRY: 0x", hex }, - [AT_NOTELF - 2] = { "NOTELF: ", hex }, - [AT_UID - 2] = { "UID: ", dec }, - [AT_EUID - 2] = { "EUID: ", dec }, - [AT_GID - 2] = { "GID: ", dec }, - [AT_EGID - 2] = { "EGID: ", dec }, - [AT_PLATFORM - 2] = { "PLATFORM: ", str }, - [AT_HWCAP - 2] = { "HWCAP: ", hex }, - [AT_CLKTCK - 2] = { "CLKTCK: ", dec }, - [AT_FPUCW - 2] = { "FPUCW: ", hex }, - [AT_DCACHEBSIZE - 2] = { "DCACHEBSIZE: 0x", hex }, - [AT_ICACHEBSIZE - 2] = { "ICACHEBSIZE: 0x", hex }, - [AT_UCACHEBSIZE - 2] = { "UCACHEBSIZE: 0x", hex }, - [AT_IGNOREPPC - 2] = { "IGNOREPPC", ignore }, - [AT_SECURE - 2] = { "SECURE: ", dec }, - [AT_BASE_PLATFORM - 2] = { "BASE_PLATFORM:", str }, - [AT_SYSINFO - 2] = { "SYSINFO: 0x", hex }, - [AT_SYSINFO_EHDR - 2] = { "SYSINFO_EHDR: 0x", hex }, - [AT_RANDOM - 2] = { "RANDOM: 0x", hex }, - [AT_HWCAP2 - 2] = { "HWCAP2: 0x", hex }, - }; - unsigned int idx = (unsigned int) (av->a_type - 2); - - if ((unsigned int) av->a_type < 2u - || (idx < sizeof (auxvars) / sizeof (auxvars[0]) - && auxvars[idx].form == ignore)) - continue; - - assert (AT_NULL == 0); - assert (AT_IGNORE == 1); - - if (av->a_type == AT_HWCAP || av->a_type == AT_HWCAP2) - { - /* These are handled in a special way per platform. */ - if (_dl_procinfo (av->a_type, av->a_un.a_val) == 0) - continue; - } - - if (idx < sizeof (auxvars) / sizeof (auxvars[0]) - && auxvars[idx].form != unknown) - { - const char *val = (char *) av->a_un.a_val; - - if (__builtin_expect (auxvars[idx].form, dec) == dec) - val = _itoa ((unsigned long int) av->a_un.a_val, - buf + sizeof buf - 1, 10, 0); - else if (__builtin_expect (auxvars[idx].form, hex) == hex) - val = _itoa ((unsigned long int) av->a_un.a_val, - buf + sizeof buf - 1, 16, 0); - - _dl_printf ("AT_%s%s\n", auxvars[idx].label, val); - - continue; - } - - /* Unknown value: print a generic line. */ - char buf2[17]; - buf2[sizeof (buf2) - 1] = '\0'; - const char *val2 = _itoa ((unsigned long int) av->a_un.a_val, - buf2 + sizeof buf2 - 1, 16, 0); - const char *val = _itoa ((unsigned long int) av->a_type, - buf + sizeof buf - 1, 16, 0); - _dl_printf ("AT_??? (0x%s): 0x%s\n", val, val2); - } -} - -#endif diff --git a/elf/dl-tls.c b/elf/dl-tls.c deleted file mode 100644 index 5aba33b3fa..0000000000 --- a/elf/dl-tls.c +++ /dev/null @@ -1,953 +0,0 @@ -/* Thread-local storage handling in the ELF dynamic linker. Generic version. - Copyright (C) 2002-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -#include <assert.h> -#include <errno.h> -#include <libintl.h> -#include <signal.h> -#include <stdlib.h> -#include <unistd.h> -#include <sys/param.h> -#include <atomic.h> - -#include <tls.h> -#include <dl-tls.h> -#include <ldsodefs.h> - -/* Amount of excess space to allocate in the static TLS area - to allow dynamic loading of modules defining IE-model TLS data. */ -#define TLS_STATIC_SURPLUS 64 + DL_NNS * 100 - - -/* Out-of-memory handler. */ -static void -__attribute__ ((__noreturn__)) -oom (void) -{ - _dl_fatal_printf ("cannot allocate memory for thread-local data: ABORT\n"); -} - - -size_t -internal_function -_dl_next_tls_modid (void) -{ - size_t result; - - if (__builtin_expect (GL(dl_tls_dtv_gaps), false)) - { - size_t disp = 0; - struct dtv_slotinfo_list *runp = GL(dl_tls_dtv_slotinfo_list); - - /* Note that this branch will never be executed during program - start since there are no gaps at that time. Therefore it - does not matter that the dl_tls_dtv_slotinfo is not allocated - yet when the function is called for the first times. - - NB: the offset +1 is due to the fact that DTV[0] is used - for something else. */ - result = GL(dl_tls_static_nelem) + 1; - if (result <= GL(dl_tls_max_dtv_idx)) - do - { - while (result - disp < runp->len) - { - if (runp->slotinfo[result - disp].map == NULL) - break; - - ++result; - assert (result <= GL(dl_tls_max_dtv_idx) + 1); - } - - if (result - disp < runp->len) - break; - - disp += runp->len; - } - while ((runp = runp->next) != NULL); - - if (result > GL(dl_tls_max_dtv_idx)) - { - /* The new index must indeed be exactly one higher than the - previous high. */ - assert (result == GL(dl_tls_max_dtv_idx) + 1); - /* There is no gap anymore. */ - GL(dl_tls_dtv_gaps) = false; - - goto nogaps; - } - } - else - { - /* No gaps, allocate a new entry. */ - nogaps: - - result = ++GL(dl_tls_max_dtv_idx); - } - - return result; -} - - -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 -_dl_determine_tlsoffset (void) -{ - size_t max_align = TLS_TCB_ALIGN; - size_t freetop = 0; - size_t freebottom = 0; - - /* The first element of the dtv slot info list is allocated. */ - assert (GL(dl_tls_dtv_slotinfo_list) != NULL); - /* There is at this point only one element in the - dl_tls_dtv_slotinfo_list list. */ - assert (GL(dl_tls_dtv_slotinfo_list)->next == NULL); - - struct dtv_slotinfo *slotinfo = GL(dl_tls_dtv_slotinfo_list)->slotinfo; - - /* Determining the offset of the various parts of the static TLS - block has several dependencies. In addition we have to work - around bugs in some toolchains. - - Each TLS block from the objects available at link time has a size - and an alignment requirement. The GNU ld computes the alignment - requirements for the data at the positions *in the file*, though. - I.e, it is not simply possible to allocate a block with the size - of the TLS program header entry. The data is layed out assuming - that the first byte of the TLS block fulfills - - p_vaddr mod p_align == &TLS_BLOCK mod p_align - - This means we have to add artificial padding at the beginning of - the TLS block. These bytes are never used for the TLS data in - this module but the first byte allocated must be aligned - according to mod p_align == 0 so that the first byte of the TLS - block is aligned according to p_vaddr mod p_align. This is ugly - and the linker can help by computing the offsets in the TLS block - assuming the first byte of the TLS block is aligned according to - p_align. - - The extra space which might be allocated before the first byte of - the TLS block need not go unused. The code below tries to use - that memory for the next TLS block. This can work if the total - memory requirement for the next TLS block is smaller than the - gap. */ - -#if TLS_TCB_AT_TP - /* We simply start with zero. */ - size_t offset = 0; - - for (size_t cnt = 0; slotinfo[cnt].map != NULL; ++cnt) - { - assert (cnt < GL(dl_tls_dtv_slotinfo_list)->len); - - size_t firstbyte = (-slotinfo[cnt].map->l_tls_firstbyte_offset - & (slotinfo[cnt].map->l_tls_align - 1)); - size_t off; - max_align = MAX (max_align, slotinfo[cnt].map->l_tls_align); - - if (freebottom - freetop >= slotinfo[cnt].map->l_tls_blocksize) - { - off = roundup (freetop + slotinfo[cnt].map->l_tls_blocksize - - firstbyte, slotinfo[cnt].map->l_tls_align) - + firstbyte; - if (off <= freebottom) - { - freetop = off; - - /* XXX For some architectures we perhaps should store the - negative offset. */ - slotinfo[cnt].map->l_tls_offset = off; - continue; - } - } - - off = roundup (offset + slotinfo[cnt].map->l_tls_blocksize - firstbyte, - slotinfo[cnt].map->l_tls_align) + firstbyte; - if (off > offset + slotinfo[cnt].map->l_tls_blocksize - + (freebottom - freetop)) - { - freetop = offset; - freebottom = off - slotinfo[cnt].map->l_tls_blocksize; - } - offset = off; - - /* XXX For some architectures we perhaps should store the - negative offset. */ - slotinfo[cnt].map->l_tls_offset = off; - } - - GL(dl_tls_static_used) = offset; - GL(dl_tls_static_size) = (roundup (offset + TLS_STATIC_SURPLUS, max_align) - + TLS_TCB_SIZE); -#elif TLS_DTV_AT_TP - /* The TLS blocks start right after the TCB. */ - size_t offset = TLS_TCB_SIZE; - - for (size_t cnt = 0; slotinfo[cnt].map != NULL; ++cnt) - { - assert (cnt < GL(dl_tls_dtv_slotinfo_list)->len); - - size_t firstbyte = (-slotinfo[cnt].map->l_tls_firstbyte_offset - & (slotinfo[cnt].map->l_tls_align - 1)); - size_t off; - max_align = MAX (max_align, slotinfo[cnt].map->l_tls_align); - - if (slotinfo[cnt].map->l_tls_blocksize <= freetop - freebottom) - { - off = roundup (freebottom, slotinfo[cnt].map->l_tls_align); - if (off - freebottom < firstbyte) - off += slotinfo[cnt].map->l_tls_align; - if (off + slotinfo[cnt].map->l_tls_blocksize - firstbyte <= freetop) - { - slotinfo[cnt].map->l_tls_offset = off - firstbyte; - freebottom = (off + slotinfo[cnt].map->l_tls_blocksize - - firstbyte); - continue; - } - } - - off = roundup (offset, slotinfo[cnt].map->l_tls_align); - if (off - offset < firstbyte) - off += slotinfo[cnt].map->l_tls_align; - - slotinfo[cnt].map->l_tls_offset = off - firstbyte; - if (off - firstbyte - offset > freetop - freebottom) - { - freebottom = offset; - freetop = off - firstbyte; - } - - offset = off + slotinfo[cnt].map->l_tls_blocksize - firstbyte; - } - - GL(dl_tls_static_used) = offset; - GL(dl_tls_static_size) = roundup (offset + TLS_STATIC_SURPLUS, - TLS_TCB_ALIGN); -#else -# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined" -#endif - - /* The alignment requirement for the static TLS block. */ - GL(dl_tls_static_align) = max_align; -} -#endif /* SHARED */ - -static void * -internal_function -allocate_dtv (void *result) -{ - dtv_t *dtv; - size_t dtv_length; - - /* We allocate a few more elements in the dtv than are needed for the - initial set of modules. This should avoid in most cases expansions - of the dtv. */ - dtv_length = GL(dl_tls_max_dtv_idx) + DTV_SURPLUS; - dtv = calloc (dtv_length + 2, sizeof (dtv_t)); - if (dtv != NULL) - { - /* This is the initial length of the dtv. */ - dtv[0].counter = dtv_length; - - /* The rest of the dtv (including the generation counter) is - Initialize with zero to indicate nothing there. */ - - /* Add the dtv to the thread data structures. */ - INSTALL_DTV (result, dtv); - } - else - result = NULL; - - return result; -} - - -/* Get size and alignment requirements of the static TLS block. */ -void -internal_function -_dl_get_tls_static_info (size_t *sizep, size_t *alignp) -{ - *sizep = GL(dl_tls_static_size); - *alignp = GL(dl_tls_static_align); -} - -/* Derive the location of the pointer to the start of the original - allocation (before alignment) from the pointer to the TCB. */ -static inline void ** -tcb_to_pointer_to_free_location (void *tcb) -{ -#if TLS_TCB_AT_TP - /* The TCB follows the TLS blocks, and the pointer to the front - follows the TCB. */ - void **original_pointer_location = tcb + TLS_TCB_SIZE; -#elif TLS_DTV_AT_TP - /* The TCB comes first, preceded by the pre-TCB, and the pointer is - before that. */ - void **original_pointer_location = tcb - TLS_PRE_TCB_SIZE - sizeof (void *); -#endif - return original_pointer_location; -} - -void * -internal_function -_dl_allocate_tls_storage (void) -{ - void *result; - size_t size = GL(dl_tls_static_size); - -#if TLS_DTV_AT_TP - /* Memory layout is: - [ TLS_PRE_TCB_SIZE ] [ TLS_TCB_SIZE ] [ TLS blocks ] - ^ This should be returned. */ - size += TLS_PRE_TCB_SIZE; -#endif - - /* Perform the allocation. Reserve space for the required alignment - and the pointer to the original allocation. */ - size_t alignment = GL(dl_tls_static_align); - void *allocated = malloc (size + alignment + sizeof (void *)); - if (__glibc_unlikely (allocated == NULL)) - return NULL; - - /* Perform alignment and allocate the DTV. */ -#if TLS_TCB_AT_TP - /* The TCB follows the TLS blocks, which determine the alignment. - (TCB alignment requirements have been taken into account when - calculating GL(dl_tls_static_align).) */ - void *aligned = (void *) roundup ((uintptr_t) allocated, alignment); - result = aligned + size - TLS_TCB_SIZE; - - /* Clear the TCB data structure. We can't ask the caller (i.e. - libpthread) to do it, because we will initialize the DTV et al. */ - memset (result, '\0', TLS_TCB_SIZE); -#elif TLS_DTV_AT_TP - /* Pre-TCB and TCB come before the TLS blocks. The layout computed - in _dl_determine_tlsoffset assumes that the TCB is aligned to the - TLS block alignment, and not just the TLS blocks after it. This - can leave an unused alignment gap between the TCB and the TLS - blocks. */ - result = (void *) roundup - (sizeof (void *) + TLS_PRE_TCB_SIZE + (uintptr_t) allocated, - alignment); - - /* Clear the TCB data structure and TLS_PRE_TCB_SIZE bytes before - it. We can't ask the caller (i.e. libpthread) to do it, because - we will initialize the DTV et al. */ - memset (result - TLS_PRE_TCB_SIZE, '\0', TLS_PRE_TCB_SIZE + TLS_TCB_SIZE); -#endif - - /* Record the value of the original pointer for later - deallocation. */ - *tcb_to_pointer_to_free_location (result) = allocated; - - result = allocate_dtv (result); - if (result == NULL) - free (allocated); - return result; -} - - -#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) -{ - if (result == NULL) - /* The memory allocation failed. */ - return NULL; - - dtv_t *dtv = GET_DTV (result); - struct dtv_slotinfo_list *listp; - 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. */ - listp = GL(dl_tls_dtv_slotinfo_list); - while (1) - { - size_t cnt; - - for (cnt = total == 0 ? 1 : 0; cnt < listp->len; ++cnt) - { - struct link_map *map; - void *dest; - - /* Check for the total number of used slots. */ - if (total + cnt > GL(dl_tls_max_dtv_idx)) - break; - - map = listp->slotinfo[cnt].map; - if (map == NULL) - /* Unused entry. */ - continue; - - /* 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.to_free = NULL; - - if (map->l_tls_offset == NO_TLS_OFFSET - || map->l_tls_offset == FORCED_DYNAMIC_TLS_OFFSET) - continue; - - 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); - dest = (char *) result - map->l_tls_offset; -#elif TLS_DTV_AT_TP - dest = (char *) result + map->l_tls_offset; -#else -# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined" -#endif - - /* Set up the DTV entry. The simplified __tls_get_addr that - some platforms use in static programs requires it. */ - dtv[map->l_tls_modid].pointer.val = dest; - - /* Copy the initialization image and clear the BSS part. */ - memset (__mempcpy (dest, map->l_tls_initimage, - map->l_tls_initimage_size), '\0', - map->l_tls_blocksize - map->l_tls_initimage_size); - } - - total += cnt; - if (total >= GL(dl_tls_max_dtv_idx)) - break; - - listp = listp->next; - assert (listp != NULL); - } - - /* The DTV version is up-to-date now. */ - dtv[0].counter = maxgen; - - return result; -} -rtld_hidden_def (_dl_allocate_tls_init) - -void * -internal_function -_dl_allocate_tls (void *mem) -{ - return _dl_allocate_tls_init (mem == NULL - ? _dl_allocate_tls_storage () - : allocate_dtv (mem)); -} -rtld_hidden_def (_dl_allocate_tls) - - -void -internal_function -_dl_deallocate_tls (void *tcb, bool dealloc_tcb) -{ - dtv_t *dtv = GET_DTV (tcb); - - /* We need to free the memory allocated for non-static TLS. */ - for (size_t cnt = 0; cnt < dtv[-1].counter; ++cnt) - free (dtv[1 + cnt].pointer.to_free); - - /* The array starts with dtv[-1]. */ - if (dtv != GL(dl_initial_dtv)) - free (dtv - 1); - - if (dealloc_tcb) - free (*tcb_to_pointer_to_free_location (tcb)); -} -rtld_hidden_def (_dl_deallocate_tls) - - -#ifdef SHARED -/* The __tls_get_addr function has two basic forms which differ in the - arguments. The IA-64 form takes two parameters, the module ID and - offset. The form used, among others, on IA-32 takes a reference to - a special structure which contain the same information. The second - form seems to be more often used (in the moment) so we default to - it. Users of the IA-64 form have to provide adequate definitions - of the following macros. */ -# ifndef GET_ADDR_ARGS -# define GET_ADDR_ARGS tls_index *ti -# define GET_ADDR_PARAM ti -# endif -# ifndef GET_ADDR_MODULE -# define GET_ADDR_MODULE ti->ti_module -# endif -# ifndef GET_ADDR_OFFSET -# define GET_ADDR_OFFSET ti->ti_offset -# endif - -/* Allocate one DTV entry. */ -static struct dtv_pointer -allocate_dtv_entry (size_t alignment, size_t size) -{ - if (powerof2 (alignment) && alignment <= _Alignof (max_align_t)) - { - /* The alignment is supported by malloc. */ - void *ptr = malloc (size); - return (struct dtv_pointer) { ptr, ptr }; - } - - /* Emulate memalign to by manually aligning a pointer returned by - malloc. First compute the size with an overflow check. */ - size_t alloc_size = size + alignment; - if (alloc_size < size) - return (struct dtv_pointer) {}; - - /* Perform the allocation. This is the pointer we need to free - later. */ - void *start = malloc (alloc_size); - if (start == NULL) - return (struct dtv_pointer) {}; - - /* Find the aligned position within the larger allocation. */ - void *aligned = (void *) roundup ((uintptr_t) start, alignment); - - return (struct dtv_pointer) { .val = aligned, .to_free = start }; -} - -static struct dtv_pointer -allocate_and_init (struct link_map *map) -{ - struct dtv_pointer result = allocate_dtv_entry - (map->l_tls_align, map->l_tls_blocksize); - if (result.val == NULL) - oom (); - - /* Initialize the memory. */ - memset (__mempcpy (result.val, map->l_tls_initimage, - map->l_tls_initimage_size), - '\0', map->l_tls_blocksize - map->l_tls_initimage_size); - - return result; -} - - -struct link_map * -_dl_update_slotinfo (unsigned long int req_modid) -{ - struct link_map *the_map = NULL; - dtv_t *dtv = THREAD_DTV (); - - /* The global dl_tls_dtv_slotinfo array contains for each module - index the generation counter current when the entry was created. - This array never shrinks so that all module indices which were - valid at some time can be used to access it. Before the first - use of a new module index in this function the array was extended - appropriately. Access also does not have to be guarded against - modifications of the array. It is assumed that pointer-size - values can be read atomically even in SMP environments. It is - possible that other threads at the same time dynamically load - code and therefore add to the slotinfo list. This is a problem - since we must not pick up any information about incomplete work. - The solution to this is to ignore all dtv slots which were - created after the one we are currently interested. We know that - dynamic loading for this module is completed and this is the last - load operation we know finished. */ - unsigned long int idx = req_modid; - struct dtv_slotinfo_list *listp = GL(dl_tls_dtv_slotinfo_list); - - while (idx >= listp->len) - { - idx -= listp->len; - listp = listp->next; - } - - if (dtv[0].counter < listp->slotinfo[idx].gen) - { - /* The generation counter for the slot is higher than what the - current dtv implements. We have to update the whole dtv but - only those entries with a generation counter <= the one for - the entry we need. */ - size_t new_gen = listp->slotinfo[idx].gen; - size_t total = 0; - - /* We have to look through the entire dtv slotinfo list. */ - listp = GL(dl_tls_dtv_slotinfo_list); - do - { - for (size_t cnt = total == 0 ? 1 : 0; cnt < listp->len; ++cnt) - { - size_t gen = listp->slotinfo[cnt].gen; - - if (gen > new_gen) - /* This is a slot for a generation younger than the - one we are handling now. It might be incompletely - set up so ignore it. */ - continue; - - /* If the entry is older than the current dtv layout we - know we don't have to handle it. */ - if (gen <= dtv[0].counter) - continue; - - /* If there is no map this means the entry is empty. */ - struct link_map *map = listp->slotinfo[cnt].map; - if (map == NULL) - { - if (dtv[-1].counter >= total + cnt) - { - /* If this modid was used at some point the memory - might still be allocated. */ - free (dtv[total + cnt].pointer.to_free); - dtv[total + cnt].pointer.val = TLS_DTV_UNALLOCATED; - dtv[total + cnt].pointer.to_free = NULL; - } - - continue; - } - - /* Check whether the current dtv array is large enough. */ - size_t modid = map->l_tls_modid; - assert (total + cnt == modid); - if (dtv[-1].counter < modid) - { - /* Resize the dtv. */ - dtv = _dl_resize_dtv (dtv); - - assert (modid <= dtv[-1].counter); - - /* Install this new dtv in the thread data - structures. */ - INSTALL_NEW_DTV (dtv); - } - - /* If there is currently memory allocate for this - dtv entry free it. */ - /* XXX Ideally we will at some point create a memory - pool. */ - free (dtv[modid].pointer.to_free); - dtv[modid].pointer.val = TLS_DTV_UNALLOCATED; - dtv[modid].pointer.to_free = NULL; - - if (modid == req_modid) - the_map = map; - } - - total += listp->len; - } - while ((listp = listp->next) != NULL); - - /* This will be the new maximum generation counter. */ - dtv[0].counter = new_gen; - } - - return the_map; -} - - -static void * -__attribute_noinline__ -tls_get_addr_tail (GET_ADDR_ARGS, dtv_t *dtv, struct link_map *the_map) -{ - /* The allocation was deferred. Do it now. */ - if (the_map == NULL) - { - /* Find the link map for this module. */ - size_t idx = GET_ADDR_MODULE; - struct dtv_slotinfo_list *listp = GL(dl_tls_dtv_slotinfo_list); - - while (idx >= listp->len) - { - idx -= listp->len; - listp = listp->next; - } - - the_map = listp->slotinfo[idx].map; - } - - /* 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 (__glibc_unlikely (the_map->l_tls_offset - != FORCED_DYNAMIC_TLS_OFFSET)) - { - __rtld_lock_lock_recursive (GL(dl_load_lock)); - 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 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)); - - dtv[GET_ADDR_MODULE].pointer.to_free = NULL; - dtv[GET_ADDR_MODULE].pointer.val = p; - - return (char *) p + GET_ADDR_OFFSET; - } - else - __rtld_lock_unlock_recursive (GL(dl_load_lock)); - } - struct dtv_pointer result = allocate_and_init (the_map); - dtv[GET_ADDR_MODULE].pointer = result; - assert (result.to_free != NULL); - - return (char *) result.val + GET_ADDR_OFFSET; -} - - -static struct link_map * -__attribute_noinline__ -update_get_addr (GET_ADDR_ARGS) -{ - struct link_map *the_map = _dl_update_slotinfo (GET_ADDR_MODULE); - dtv_t *dtv = THREAD_DTV (); - - void *p = dtv[GET_ADDR_MODULE].pointer.val; - - 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. */ -void * -__tls_get_addr (GET_ADDR_ARGS) -{ - dtv_t *dtv = THREAD_DTV (); - - 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 (__glibc_unlikely (p == TLS_DTV_UNALLOCATED)) - return tls_get_addr_tail (GET_ADDR_PARAM, dtv, NULL); - - return (char *) p + GET_ADDR_OFFSET; -} -#endif - - -/* Look up the module's TLS block as for __tls_get_addr, - but never touch anything. Return null if it's not allocated yet. */ -void * -_dl_tls_get_addr_soft (struct link_map *l) -{ - if (__glibc_unlikely (l->l_tls_modid == 0)) - /* This module has no TLS segment. */ - return NULL; - - dtv_t *dtv = THREAD_DTV (); - 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. */ - - if (l->l_tls_modid >= dtv[-1].counter) - /* Nope. */ - return NULL; - - size_t idx = l->l_tls_modid; - struct dtv_slotinfo_list *listp = GL(dl_tls_dtv_slotinfo_list); - while (idx >= listp->len) - { - idx -= listp->len; - listp = listp->next; - } - - /* We've reached the slot for this module. - If its generation counter is higher than the DTV's, - this thread does not know about this module yet. */ - if (dtv[0].counter < listp->slotinfo[idx].gen) - return NULL; - } - - void *data = dtv[l->l_tls_modid].pointer.val; - 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; - - return data; -} - - -void -_dl_add_to_slotinfo (struct link_map *l) -{ - /* Now that we know the object is loaded successfully add - modules containing TLS data to the dtv info table. We - might have to increase its size. */ - struct dtv_slotinfo_list *listp; - struct dtv_slotinfo_list *prevp; - size_t idx = l->l_tls_modid; - - /* Find the place in the dtv slotinfo list. */ - listp = GL(dl_tls_dtv_slotinfo_list); - prevp = NULL; /* Needed to shut up gcc. */ - do - { - /* Does it fit in the array of this list element? */ - if (idx < listp->len) - break; - idx -= listp->len; - prevp = listp; - listp = listp->next; - } - while (listp != NULL); - - if (listp == NULL) - { - /* When we come here it means we have to add a new element - to the slotinfo list. And the new module must be in - the first slot. */ - assert (idx == 0); - - listp = prevp->next = (struct dtv_slotinfo_list *) - malloc (sizeof (struct dtv_slotinfo_list) - + TLS_SLOTINFO_SURPLUS * sizeof (struct dtv_slotinfo)); - if (listp == NULL) - { - /* We ran out of memory. We will simply fail this - call but don't undo anything we did so far. The - application will crash or be terminated anyway very - soon. */ - - /* We have to do this since some entries in the dtv - slotinfo array might already point to this - generation. */ - ++GL(dl_tls_generation); - - _dl_signal_error (ENOMEM, "dlopen", NULL, N_("\ -cannot create TLS data structures")); - } - - listp->len = TLS_SLOTINFO_SURPLUS; - listp->next = NULL; - memset (listp->slotinfo, '\0', - TLS_SLOTINFO_SURPLUS * sizeof (struct dtv_slotinfo)); - } - - /* Add the information into the slotinfo data structure. */ - listp->slotinfo[idx].map = l; - listp->slotinfo[idx].gen = GL(dl_tls_generation) + 1; -} diff --git a/elf/dl-trampoline.c b/elf/dl-trampoline.c deleted file mode 100644 index 3ca89f3879..0000000000 --- a/elf/dl-trampoline.c +++ /dev/null @@ -1 +0,0 @@ -#error "Architecture specific PLT trampolines must be defined." diff --git a/elf/dl-tunable-types.h b/elf/dl-tunable-types.h deleted file mode 100644 index 1d516df08f..0000000000 --- a/elf/dl-tunable-types.h +++ /dev/null @@ -1,62 +0,0 @@ -/* Tunable type information. - - Copyright (C) 2016-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -#ifndef _TUNABLE_TYPES_H_ -# define _TUNABLE_TYPES_H_ -#include <stddef.h> - -typedef enum -{ - TUNABLE_TYPE_INT_32, - TUNABLE_TYPE_UINT_64, - TUNABLE_TYPE_SIZE_T, - TUNABLE_TYPE_STRING -} tunable_type_code_t; - -typedef struct -{ - tunable_type_code_t type_code; - int64_t min; - int64_t max; -} tunable_type_t; - -typedef union -{ - int64_t numval; - const char *strval; -} tunable_val_t; - -typedef void (*tunable_callback_t) (tunable_val_t *); - -/* Security level for tunables. This decides what to do with individual - tunables for AT_SECURE binaries. */ -typedef enum -{ - /* Erase the tunable for AT_SECURE binaries so that child processes don't - read it. */ - TUNABLE_SECLEVEL_SXID_ERASE = 0, - /* Ignore the tunable for AT_SECURE binaries, but don't erase it, so that - child processes can read it. */ - TUNABLE_SECLEVEL_SXID_IGNORE = 1, - /* Read the tunable. */ - TUNABLE_SECLEVEL_NONE = 2, -} tunable_seclevel_t; - - -#endif diff --git a/elf/dl-tunables.c b/elf/dl-tunables.c deleted file mode 100644 index 76e8c5cae1..0000000000 --- a/elf/dl-tunables.c +++ /dev/null @@ -1,490 +0,0 @@ -/* The tunable framework. See the README.tunables to know how to use the - tunable in a glibc module. - - Copyright (C) 2016-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -#include <stdint.h> -#include <stdbool.h> -#include <unistd.h> -#include <stdlib.h> -#include <sysdep.h> -#include <fcntl.h> -#include <ldsodefs.h> - -#define TUNABLES_INTERNAL 1 -#include "dl-tunables.h" - -#if TUNABLES_FRONTEND == TUNABLES_FRONTEND_valstring -# define GLIBC_TUNABLES "GLIBC_TUNABLES" -#endif - -/* Compare environment or tunable names, bounded by the name hardcoded in - glibc. */ -static bool -is_name (const char *orig, const char *envname) -{ - for (;*orig != '\0' && *envname != '\0'; envname++, orig++) - if (*orig != *envname) - break; - - /* The ENVNAME is immediately followed by a value. */ - if (*orig == '\0' && *envname == '=') - return true; - else - return false; -} - -#if TUNABLES_FRONTEND == TUNABLES_FRONTEND_valstring -static char * -tunables_strdup (const char *in) -{ - size_t i = 0; - - while (in[i++] != '\0'); - char *out = __sbrk (i); - - /* FIXME: In reality if the allocation fails, __sbrk will crash attempting to - set the thread-local errno since the TCB has not yet been set up. This - needs to be fixed with an __sbrk implementation that does not set - errno. */ - if (out == (void *)-1) - return NULL; - - i--; - - while (i-- > 0) - out[i] = in[i]; - - return out; -} -#endif - -static char ** -get_next_env (char **envp, char **name, size_t *namelen, char **val, - char ***prev_envp) -{ - while (envp != NULL && *envp != NULL) - { - char **prev = envp; - char *envline = *envp++; - int len = 0; - - while (envline[len] != '\0' && envline[len] != '=') - len++; - - /* Just the name and no value, go to the next one. */ - if (envline[len] == '\0') - continue; - - *name = envline; - *namelen = len; - *val = &envline[len + 1]; - *prev_envp = prev; - - return envp; - } - - return NULL; -} - -/* A stripped down strtoul-like implementation for very early use. It does not - set errno if the result is outside bounds because it gets called before - errno may have been set up. */ -static uint64_t -tunables_strtoul (const char *nptr) -{ - uint64_t result = 0; - long int sign = 1; - unsigned max_digit; - - while (*nptr == ' ' || *nptr == '\t') - ++nptr; - - if (*nptr == '-') - { - sign = -1; - ++nptr; - } - else if (*nptr == '+') - ++nptr; - - if (*nptr < '0' || *nptr > '9') - return 0UL; - - int base = 10; - max_digit = 9; - if (*nptr == '0') - { - if (nptr[1] == 'x' || nptr[1] == 'X') - { - base = 16; - nptr += 2; - } - else - { - base = 8; - max_digit = 7; - } - } - - while (1) - { - int digval; - if (*nptr >= '0' && *nptr <= '0' + max_digit) - digval = *nptr - '0'; - else if (base == 16) - { - if (*nptr >= 'a' && *nptr <= 'f') - digval = *nptr - 'a' + 10; - else if (*nptr >= 'A' && *nptr <= 'F') - digval = *nptr - 'A' + 10; - else - break; - } - else - break; - - if (result >= (UINT64_MAX - digval) / base) - return UINT64_MAX; - result *= base; - result += digval; - ++nptr; - } - - return result * sign; -} - -#define TUNABLE_SET_VAL_IF_VALID_RANGE(__cur, __val, __type, __default_min, \ - __default_max) \ -({ \ - __type min = (__cur)->type.min; \ - __type max = (__cur)->type.max; \ - \ - if (min == max) \ - { \ - min = __default_min; \ - max = __default_max; \ - } \ - \ - if ((__type) (__val) >= min && (__type) (val) <= max) \ - { \ - (__cur)->val.numval = val; \ - (__cur)->initialized = true; \ - } \ -}) - -static void -do_tunable_update_val (tunable_t *cur, const void *valp) -{ - uint64_t val; - - if (cur->type.type_code != TUNABLE_TYPE_STRING) - val = *((int64_t *) valp); - - switch (cur->type.type_code) - { - case TUNABLE_TYPE_INT_32: - { - TUNABLE_SET_VAL_IF_VALID_RANGE (cur, val, int64_t, INT32_MIN, INT32_MAX); - break; - } - case TUNABLE_TYPE_UINT_64: - { - TUNABLE_SET_VAL_IF_VALID_RANGE (cur, val, uint64_t, 0, UINT64_MAX); - break; - } - case TUNABLE_TYPE_SIZE_T: - { - TUNABLE_SET_VAL_IF_VALID_RANGE (cur, val, uint64_t, 0, SIZE_MAX); - break; - } - case TUNABLE_TYPE_STRING: - { - cur->val.strval = valp; - break; - } - default: - __builtin_unreachable (); - } -} - -/* Validate range of the input value and initialize the tunable CUR if it looks - good. */ -static void -tunable_initialize (tunable_t *cur, const char *strval) -{ - uint64_t val; - const void *valp; - - if (cur->type.type_code != TUNABLE_TYPE_STRING) - { - val = tunables_strtoul (strval); - valp = &val; - } - else - { - cur->initialized = true; - valp = strval; - } - do_tunable_update_val (cur, valp); -} - -void -__tunable_set_val (tunable_id_t id, void *valp) -{ - tunable_t *cur = &tunable_list[id]; - - do_tunable_update_val (cur, valp); -} - -#if TUNABLES_FRONTEND == TUNABLES_FRONTEND_valstring -/* Parse the tunable string TUNESTR and adjust it to drop any tunables that may - be unsafe for AT_SECURE processes so that it can be used as the new - environment variable value for GLIBC_TUNABLES. VALSTRING is the original - environment variable string which we use to make NULL terminated values so - that we don't have to allocate memory again for it. */ -static void -parse_tunables (char *tunestr, char *valstring) -{ - if (tunestr == NULL || *tunestr == '\0') - return; - - char *p = tunestr; - - while (true) - { - char *name = p; - size_t len = 0; - - /* First, find where the name ends. */ - while (p[len] != '=' && p[len] != ':' && p[len] != '\0') - len++; - - /* If we reach the end of the string before getting a valid name-value - pair, bail out. */ - if (p[len] == '\0') - return; - - /* We did not find a valid name-value pair before encountering the - colon. */ - if (p[len]== ':') - { - p += len + 1; - continue; - } - - p += len + 1; - - /* Take the value from the valstring since we need to NULL terminate it. */ - char *value = &valstring[p - tunestr]; - len = 0; - - while (p[len] != ':' && p[len] != '\0') - len++; - - /* Add the tunable if it exists. */ - for (size_t i = 0; i < sizeof (tunable_list) / sizeof (tunable_t); i++) - { - tunable_t *cur = &tunable_list[i]; - - if (is_name (cur->name, name)) - { - /* If we are in a secure context (AT_SECURE) then ignore the tunable - unless it is explicitly marked as secure. Tunable values take - precendence over their envvar aliases. */ - if (__libc_enable_secure) - { - if (cur->security_level == TUNABLE_SECLEVEL_SXID_ERASE) - { - if (p[len] == '\0') - { - /* Last tunable in the valstring. Null-terminate and - return. */ - *name = '\0'; - return; - } - else - { - /* Remove the current tunable from the string. We do - this by overwriting the string starting from NAME - (which is where the current tunable begins) with - the remainder of the string. We then have P point - to NAME so that we continue in the correct - position in the valstring. */ - char *q = &p[len + 1]; - p = name; - while (*q != '\0') - *name++ = *q++; - name[0] = '\0'; - len = 0; - } - } - - if (cur->security_level != TUNABLE_SECLEVEL_NONE) - break; - } - - value[len] = '\0'; - tunable_initialize (cur, value); - break; - } - } - - if (p[len] == '\0') - return; - else - p += len + 1; - } -} -#endif - -/* Enable the glibc.malloc.check tunable in SETUID/SETGID programs only when - the system administrator has created the /etc/suid-debug file. This is a - special case where we want to conditionally enable/disable a tunable even - for setuid binaries. We use the special version of access() to avoid - setting ERRNO, which is a TLS variable since TLS has not yet been set - up. */ -static inline void -__always_inline -maybe_enable_malloc_check (void) -{ - tunable_id_t id = TUNABLE_ENUM_NAME (glibc, malloc, check); - if (__libc_enable_secure && __access_noerrno ("/etc/suid-debug", F_OK) == 0) - tunable_list[id].security_level = TUNABLE_SECLEVEL_NONE; -} - -/* Initialize the tunables list from the environment. For now we only use the - ENV_ALIAS to find values. Later we will also use the tunable names to find - values. */ -void -__tunables_init (char **envp) -{ - char *envname = NULL; - char *envval = NULL; - size_t len = 0; - char **prev_envp = envp; - - maybe_enable_malloc_check (); - - while ((envp = get_next_env (envp, &envname, &len, &envval, - &prev_envp)) != NULL) - { -#if TUNABLES_FRONTEND == TUNABLES_FRONTEND_valstring - if (is_name (GLIBC_TUNABLES, envname)) - { - char *new_env = tunables_strdup (envname); - if (new_env != NULL) - parse_tunables (new_env + len + 1, envval); - /* Put in the updated envval. */ - *prev_envp = new_env; - continue; - } -#endif - - for (int i = 0; i < sizeof (tunable_list) / sizeof (tunable_t); i++) - { - tunable_t *cur = &tunable_list[i]; - - /* Skip over tunables that have either been set already or should be - skipped. */ - if (cur->initialized || cur->env_alias == NULL) - continue; - - const char *name = cur->env_alias; - - /* We have a match. Initialize and move on to the next line. */ - if (is_name (name, envname)) - { - /* For AT_SECURE binaries, we need to check the security settings of - the tunable and decide whether we read the value and also whether - we erase the value so that child processes don't inherit them in - the environment. */ - if (__libc_enable_secure) - { - if (cur->security_level == TUNABLE_SECLEVEL_SXID_ERASE) - { - /* Erase the environment variable. */ - char **ep = prev_envp; - - while (*ep != NULL) - { - if (is_name (name, *ep)) - { - char **dp = ep; - - do - dp[0] = dp[1]; - while (*dp++); - } - else - ++ep; - } - /* Reset the iterator so that we read the environment again - from the point we erased. */ - envp = prev_envp; - } - - if (cur->security_level != TUNABLE_SECLEVEL_NONE) - continue; - } - - tunable_initialize (cur, envval); - break; - } - } - } -} - -/* Set the tunable value. This is called by the module that the tunable exists - in. */ -void -__tunable_get_val (tunable_id_t id, void *valp, tunable_callback_t callback) -{ - tunable_t *cur = &tunable_list[id]; - - switch (cur->type.type_code) - { - case TUNABLE_TYPE_UINT_64: - { - *((uint64_t *) valp) = (uint64_t) cur->val.numval; - break; - } - case TUNABLE_TYPE_INT_32: - { - *((int32_t *) valp) = (int32_t) cur->val.numval; - break; - } - case TUNABLE_TYPE_SIZE_T: - { - *((size_t *) valp) = (size_t) cur->val.numval; - break; - } - case TUNABLE_TYPE_STRING: - { - *((const char **)valp) = cur->val.strval; - break; - } - default: - __builtin_unreachable (); - } - - if (cur->initialized && callback != NULL) - callback (&cur->val); -} - -rtld_hidden_def (__tunable_get_val) diff --git a/elf/dl-tunables.h b/elf/dl-tunables.h deleted file mode 100644 index 6c49dcbf47..0000000000 --- a/elf/dl-tunables.h +++ /dev/null @@ -1,115 +0,0 @@ -/* The tunable framework. See the README to know how to use the tunable in - a glibc module. - - Copyright (C) 2016-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -#ifndef _TUNABLES_H_ -#define _TUNABLES_H_ - -#if !HAVE_TUNABLES -static inline void -__always_inline -__tunables_init (char **unused __attribute__ ((unused))) -{ - /* This is optimized out if tunables are not enabled. */ -} -#else - -# include <stddef.h> -# include "dl-tunable-types.h" - -/* A tunable. */ -struct _tunable -{ - const char *name; /* Internal name of the tunable. */ - tunable_type_t type; /* Data type of the tunable. */ - tunable_val_t val; /* The value. */ - bool initialized; /* Flag to indicate that the tunable is - initialized. */ - tunable_seclevel_t security_level; /* Specify the security level for the - tunable with respect to AT_SECURE - programs. See description of - tunable_seclevel_t to see a - description of the values. - - Note that even if the tunable is - read, it may not get used by the - target module if the value is - considered unsafe. */ - /* Compatibility elements. */ - const char *env_alias; /* The compatibility environment - variable name. */ -}; - -typedef struct _tunable tunable_t; - -/* Full name for a tunable is top_ns.tunable_ns.id. */ -# define TUNABLE_NAME_S(top,ns,id) #top "." #ns "." #id - -# define TUNABLE_ENUM_NAME(__top,__ns,__id) TUNABLE_ENUM_NAME1 (__top,__ns,__id) -# define TUNABLE_ENUM_NAME1(__top,__ns,__id) __top ## _ ## __ns ## _ ## __id - -# include "dl-tunable-list.h" - -extern void __tunables_init (char **); -extern void __tunable_get_val (tunable_id_t, void *, tunable_callback_t); -extern void __tunable_set_val (tunable_id_t, void *); -rtld_hidden_proto (__tunables_init) -rtld_hidden_proto (__tunable_get_val) - -/* Define TUNABLE_GET and TUNABLE_SET in short form if TOP_NAMESPACE and - TUNABLE_NAMESPACE are defined. This is useful shorthand to get and set - tunables within a module. */ -#if defined TOP_NAMESPACE && defined TUNABLE_NAMESPACE -# define TUNABLE_GET(__id, __type, __cb) \ - TUNABLE_GET_FULL (TOP_NAMESPACE, TUNABLE_NAMESPACE, __id, __type, __cb) -# define TUNABLE_SET(__id, __type, __val) \ - TUNABLE_SET_FULL (TOP_NAMESPACE, TUNABLE_NAMESPACE, __id, __type, __val) -#else -# define TUNABLE_GET(__top, __ns, __id, __type, __cb) \ - TUNABLE_GET_FULL (__top, __ns, __id, __type, __cb) -# define TUNABLE_SET(__top, __ns, __id, __type, __val) \ - TUNABLE_SET_FULL (__top, __ns, __id, __type, __val) -#endif - -/* Get and return a tunable value. If the tunable was set externally and __CB - is defined then call __CB before returning the value. */ -# define TUNABLE_GET_FULL(__top, __ns, __id, __type, __cb) \ -({ \ - tunable_id_t id = TUNABLE_ENUM_NAME (__top, __ns, __id); \ - __type ret; \ - __tunable_get_val (id, &ret, __cb); \ - ret; \ -}) - -/* Set a tunable value. */ -# define TUNABLE_SET_FULL(__top, __ns, __id, __type, __val) \ -({ \ - __tunable_set_val (TUNABLE_ENUM_NAME (__top, __ns, __id), \ - & (__type) {__val}); \ -}) - -/* Namespace sanity for callback functions. Use this macro to keep the - namespace of the modules clean. */ -# define TUNABLE_CALLBACK(__name) _dl_tunable_ ## __name - -# define TUNABLES_FRONTEND_valstring 1 -/* The default value for TUNABLES_FRONTEND. */ -# define TUNABLES_FRONTEND_yes TUNABLES_FRONTEND_valstring -#endif -#endif diff --git a/elf/dl-tunables.list b/elf/dl-tunables.list deleted file mode 100644 index 41ce9afa28..0000000000 --- a/elf/dl-tunables.list +++ /dev/null @@ -1,87 +0,0 @@ -# Copyright (C) 2016-2017 Free Software Foundation, Inc. -# This file is part of the GNU C Library. - -# The GNU C Library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. - -# The GNU C Library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. - -# You should have received a copy of the GNU Lesser General Public -# License along with the GNU C Library; if not, see -# <http://www.gnu.org/licenses/>. - -# Allowed attributes for tunables: -# -# type: Defaults to STRING -# minval: Optional minimum acceptable value -# maxval: Optional maximum acceptable value -# env_alias: An alias environment variable -# security_level: Specify security level of the tunable. Valid values are: -# -# SXID_ERASE: (default) Don't read for AT_SECURE binaries and -# removed so that child processes can't read it. -# SXID_IGNORE: Don't read for AT_SECURE binaries, but retained for -# non-AT_SECURE subprocesses. -# NONE: Read all the time. - -glibc { - malloc { - check { - type: INT_32 - minval: 0 - maxval: 3 - env_alias: MALLOC_CHECK_ - } - top_pad { - type: SIZE_T - env_alias: MALLOC_TOP_PAD_ - security_level: SXID_IGNORE - } - perturb { - type: INT_32 - minval: 0 - maxval: 0xff - env_alias: MALLOC_PERTURB_ - security_level: SXID_IGNORE - } - mmap_threshold { - type: SIZE_T - env_alias: MALLOC_MMAP_THRESHOLD_ - security_level: SXID_IGNORE - } - trim_threshold { - type: SIZE_T - env_alias: MALLOC_TRIM_THRESHOLD_ - security_level: SXID_IGNORE - } - mmap_max { - type: INT_32 - env_alias: MALLOC_MMAP_MAX_ - security_level: SXID_IGNORE - } - arena_max { - type: SIZE_T - env_alias: MALLOC_ARENA_MAX - minval: 1 - security_level: SXID_IGNORE - } - arena_test { - type: SIZE_T - env_alias: MALLOC_ARENA_TEST - minval: 1 - security_level: SXID_IGNORE - } - } - tune { - hwcap_mask { - type: UINT_64 - env_alias: LD_HWCAP_MASK - default: HWCAP_IMPORTANT - } - } -} diff --git a/elf/dl-unmap-segments.h b/elf/dl-unmap-segments.h deleted file mode 100644 index f37e183943..0000000000 --- a/elf/dl-unmap-segments.h +++ /dev/null @@ -1,35 +0,0 @@ -/* Unmap a shared object's segments. Generic version. - Copyright (C) 2014-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -#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 deleted file mode 100644 index c00078e5e4..0000000000 --- a/elf/dl-version.c +++ /dev/null @@ -1,389 +0,0 @@ -/* Handle symbol and library versioning. - Copyright (C) 1997-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. - - 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 <elf.h> -#include <errno.h> -#include <libintl.h> -#include <stdlib.h> -#include <string.h> -#include <ldsodefs.h> -#include <_itoa.h> - -#include <assert.h> - - -#define make_string(string, rest...) \ - ({ \ - const char *all[] = { string, ## rest }; \ - size_t len, cnt; \ - char *result, *cp; \ - \ - len = 1; \ - for (cnt = 0; cnt < sizeof (all) / sizeof (all[0]); ++cnt) \ - len += strlen (all[cnt]); \ - \ - cp = result = alloca (len); \ - for (cnt = 0; cnt < sizeof (all) / sizeof (all[0]); ++cnt) \ - cp = __stpcpy (cp, all[cnt]); \ - \ - result; \ - }) - - -static inline struct link_map * -__attribute ((always_inline)) -find_needed (const char *name, struct link_map *map) -{ - struct link_map *tmap; - unsigned int n; - - for (tmap = GL(dl_ns)[map->l_ns]._ns_loaded; tmap != NULL; - tmap = tmap->l_next) - if (_dl_name_match_p (name, tmap)) - return tmap; - - /* The required object is not in the global scope, look to see if it is - a dependency of the current object. */ - for (n = 0; n < map->l_searchlist.r_nlist; n++) - if (_dl_name_match_p (name, map->l_searchlist.r_list[n])) - return map->l_searchlist.r_list[n]; - - /* Should never happen. */ - return NULL; -} - - -static int -internal_function -match_symbol (const char *name, Lmid_t ns, ElfW(Word) hash, const char *string, - struct link_map *map, int verbose, int weak) -{ - const char *strtab = (const void *) D_PTR (map, l_info[DT_STRTAB]); - ElfW(Addr) def_offset; - ElfW(Verdef) *def; - /* Initialize to make the compiler happy. */ - const char *errstring = NULL; - int result = 0; - - /* Display information about what we are doing while debugging. */ - 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 (__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 - only print a message if verbose output is requested. */ - if (verbose) - { - /* XXX We cannot translate the messages. */ - errstring = make_string ("\ -no version information available (required by ", name, ")"); - goto call_cerror; - } - return 0; - } - - def_offset = map->l_info[VERSYMIDX (DT_VERDEF)]->d_un.d_ptr; - assert (def_offset != 0); - - def = (ElfW(Verdef) *) ((char *) map->l_addr + def_offset); - while (1) - { - /* Currently the version number of the definition entry is 1. - Make sure all we see is this version. */ - if (__builtin_expect (def->vd_version, 1) != 1) - { - char buf[20]; - buf[sizeof (buf) - 1] = '\0'; - /* XXX We cannot translate the message. */ - errstring = make_string ("unsupported version ", - _itoa (def->vd_version, - &buf[sizeof (buf) - 1], 10, 0), - " of Verdef record"); - result = 1; - goto call_cerror; - } - - /* Compare the hash values. */ - if (hash == def->vd_hash) - { - ElfW(Verdaux) *aux = (ElfW(Verdaux) *) ((char *) def + def->vd_aux); - - /* To be safe, compare the string as well. */ - if (__builtin_expect (strcmp (string, strtab + aux->vda_name), 0) - == 0) - /* Bingo! */ - return 0; - } - - /* If no more definitions we failed to find what we want. */ - if (def->vd_next == 0) - break; - - /* Next definition. */ - def = (ElfW(Verdef) *) ((char *) def + def->vd_next); - } - - /* Symbol not found. If it was a weak reference it is not fatal. */ - if (__glibc_likely (weak)) - { - if (verbose) - { - /* XXX We cannot translate the message. */ - errstring = make_string ("weak version `", string, - "' not found (required by ", name, ")"); - goto call_cerror; - } - return 0; - } - - /* XXX We cannot translate the message. */ - errstring = make_string ("version `", string, "' not found (required by ", - name, ")"); - result = 1; - call_cerror: - _dl_signal_cerror (0, DSO_FILENAME (map->l_name), - N_("version lookup error"), errstring); - return result; -} - - -int -internal_function -_dl_check_map_versions (struct link_map *map, int verbose, int trace_mode) -{ - int result = 0; - const char *strtab; - /* Pointer to section with needed versions. */ - ElfW(Dyn) *dyn; - /* Pointer to dynamic section with definitions. */ - ElfW(Dyn) *def; - /* We need to find out which is the highest version index used - in a dependecy. */ - unsigned int ndx_high = 0; - /* Initialize to make the compiler happy. */ - const char *errstring = NULL; - int errval = 0; - - /* If we don't have a string table, we must be ok. */ - if (map->l_info[DT_STRTAB] == NULL) - return 0; - strtab = (const void *) D_PTR (map, l_info[DT_STRTAB]); - - dyn = map->l_info[VERSYMIDX (DT_VERNEED)]; - def = map->l_info[VERSYMIDX (DT_VERDEF)]; - - if (dyn != NULL) - { - /* This file requires special versions from its dependencies. */ - ElfW(Verneed) *ent = (ElfW(Verneed) *) (map->l_addr + dyn->d_un.d_ptr); - - /* Currently the version number of the needed entry is 1. - Make sure all we see is this version. */ - if (__builtin_expect (ent->vn_version, 1) != 1) - { - char buf[20]; - buf[sizeof (buf) - 1] = '\0'; - /* XXX We cannot translate the message. */ - errstring = make_string ("unsupported version ", - _itoa (ent->vn_version, - &buf[sizeof (buf) - 1], 10, 0), - " of Verneed record\n"); - call_error: - _dl_signal_error (errval, DSO_FILENAME (map->l_name), - NULL, errstring); - } - - while (1) - { - ElfW(Vernaux) *aux; - struct link_map *needed = find_needed (strtab + ent->vn_file, map); - - /* If NEEDED is NULL this means a dependency was not found - and no stub entry was created. This should never happen. */ - assert (needed != NULL); - - /* Make sure this is no stub we created because of a missing - dependency. */ - if (__builtin_expect (! trace_mode, 1) - || ! __builtin_expect (needed->l_faked, 0)) - { - /* NEEDED is the map for the file we need. Now look for the - dependency symbols. */ - aux = (ElfW(Vernaux) *) ((char *) ent + ent->vn_aux); - while (1) - { - /* Match the symbol. */ - result |= match_symbol (DSO_FILENAME (map->l_name), - map->l_ns, aux->vna_hash, - strtab + aux->vna_name, - needed->l_real, verbose, - aux->vna_flags & VER_FLG_WEAK); - - /* Compare the version index. */ - if ((unsigned int) (aux->vna_other & 0x7fff) > ndx_high) - ndx_high = aux->vna_other & 0x7fff; - - if (aux->vna_next == 0) - /* No more symbols. */ - break; - - /* Next symbol. */ - aux = (ElfW(Vernaux) *) ((char *) aux + aux->vna_next); - } - } - - if (ent->vn_next == 0) - /* No more dependencies. */ - break; - - /* Next dependency. */ - ent = (ElfW(Verneed) *) ((char *) ent + ent->vn_next); - } - } - - /* We also must store the names of the defined versions. Determine - the maximum index here as well. - - XXX We could avoid the loop by just taking the number of definitions - as an upper bound of new indeces. */ - if (def != NULL) - { - ElfW(Verdef) *ent; - ent = (ElfW(Verdef) *) (map->l_addr + def->d_un.d_ptr); - while (1) - { - if ((unsigned int) (ent->vd_ndx & 0x7fff) > ndx_high) - ndx_high = ent->vd_ndx & 0x7fff; - - if (ent->vd_next == 0) - /* No more definitions. */ - break; - - ent = (ElfW(Verdef) *) ((char *) ent + ent->vd_next); - } - } - - if (ndx_high > 0) - { - /* Now we are ready to build the array with the version names - which can be indexed by the version index in the VERSYM - section. */ - map->l_versions = (struct r_found_version *) - calloc (ndx_high + 1, sizeof (*map->l_versions)); - if (__glibc_unlikely (map->l_versions == NULL)) - { - errstring = N_("cannot allocate version reference table"); - errval = ENOMEM; - goto call_error; - } - - /* Store the number of available symbols. */ - map->l_nversions = ndx_high + 1; - - /* Compute the pointer to the version symbols. */ - map->l_versyms = (void *) D_PTR (map, l_info[VERSYMIDX (DT_VERSYM)]); - - if (dyn != NULL) - { - ElfW(Verneed) *ent; - ent = (ElfW(Verneed) *) (map->l_addr + dyn->d_un.d_ptr); - while (1) - { - ElfW(Vernaux) *aux; - aux = (ElfW(Vernaux) *) ((char *) ent + ent->vn_aux); - while (1) - { - ElfW(Half) ndx = aux->vna_other & 0x7fff; - /* In trace mode, dependencies may be missing. */ - if (__glibc_likely (ndx < map->l_nversions)) - { - map->l_versions[ndx].hash = aux->vna_hash; - map->l_versions[ndx].hidden = aux->vna_other & 0x8000; - map->l_versions[ndx].name = &strtab[aux->vna_name]; - map->l_versions[ndx].filename = &strtab[ent->vn_file]; - } - - if (aux->vna_next == 0) - /* No more symbols. */ - break; - - /* Advance to next symbol. */ - aux = (ElfW(Vernaux) *) ((char *) aux + aux->vna_next); - } - - if (ent->vn_next == 0) - /* No more dependencies. */ - break; - - /* Advance to next dependency. */ - ent = (ElfW(Verneed) *) ((char *) ent + ent->vn_next); - } - } - - /* And insert the defined versions. */ - if (def != NULL) - { - ElfW(Verdef) *ent; - ent = (ElfW(Verdef) *) (map->l_addr + def->d_un.d_ptr); - while (1) - { - ElfW(Verdaux) *aux; - aux = (ElfW(Verdaux) *) ((char *) ent + ent->vd_aux); - - if ((ent->vd_flags & VER_FLG_BASE) == 0) - { - /* The name of the base version should not be - available for matching a versioned symbol. */ - ElfW(Half) ndx = ent->vd_ndx & 0x7fff; - map->l_versions[ndx].hash = ent->vd_hash; - map->l_versions[ndx].name = &strtab[aux->vda_name]; - map->l_versions[ndx].filename = NULL; - } - - if (ent->vd_next == 0) - /* No more definitions. */ - break; - - ent = (ElfW(Verdef) *) ((char *) ent + ent->vd_next); - } - } - } - - return result; -} - - -int -internal_function -_dl_check_all_versions (struct link_map *map, int verbose, int trace_mode) -{ - struct link_map *l; - int result = 0; - - for (l = map; l != NULL; l = l->l_next) - result |= (! l->l_faked - && _dl_check_map_versions (l, verbose, trace_mode)); - - return result; -} diff --git a/elf/dl-writev.h b/elf/dl-writev.h deleted file mode 100644 index 4db083bef6..0000000000 --- a/elf/dl-writev.h +++ /dev/null @@ -1,56 +0,0 @@ -/* Message-writing for the dynamic linker. Generic version. - Copyright (C) 2013-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -#include <sys/uio.h> -#include <ldsodefs.h> -#include <libc-lock.h> - -/* This is used from only one place: dl-misc.c:_dl_debug_vdprintf. - Hence it's in a header with the expectation it will be inlined. - - This is writev, but with a constraint added and others loosened: - - 1. Under RTLD_PRIVATE_ERRNO, it must not clobber the private errno - when another thread holds the dl_load_lock. - 2. It is not obliged to detect and report errors at all. - 3. It's not really obliged to deliver a single atomic write - (though it may be preferable). */ - -static inline void -_dl_writev (int fd, const struct iovec *iov, size_t niov) -{ - /* Note that if __writev is an implementation that calls malloc, - this will cause linking problems building the dynamic linker. */ - -#if RTLD_PRIVATE_ERRNO - /* We have to take this lock just to be sure we don't clobber the private - 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 (__glibc_unlikely (_dl_starting_up)) - __writev (fd, iov, niov); - else - { - __rtld_lock_lock_recursive (GL(dl_load_lock)); - __writev (fd, iov, niov); - __rtld_lock_unlock_recursive (GL(dl_load_lock)); - } -#else - __writev (fd, iov, niov); -#endif -} diff --git a/elf/do-rel.h b/elf/do-rel.h deleted file mode 100644 index 70071e5c44..0000000000 --- a/elf/do-rel.h +++ /dev/null @@ -1,191 +0,0 @@ -/* Do relocations for ELF dynamic linking. - Copyright (C) 1995-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -/* This file may be included twice, to define both - `elf_dynamic_do_rel' and `elf_dynamic_do_rela'. */ - -#ifdef DO_RELA -# define elf_dynamic_do_Rel elf_dynamic_do_Rela -# define Rel Rela -# define elf_machine_rel elf_machine_rela -# define elf_machine_rel_relative elf_machine_rela_relative -#endif - -#ifndef DO_ELF_MACHINE_REL_RELATIVE -# define DO_ELF_MACHINE_REL_RELATIVE(map, l_addr, relative) \ - elf_machine_rel_relative (l_addr, relative, \ - (void *) (l_addr + relative->r_offset)) -#endif - -/* Perform the relocations in MAP on the running program image as specified - by RELTAG, SZTAG. If LAZY is nonzero, this is the first pass on PLT - relocations; they should be set up to call _dl_runtime_resolve, rather - than fully resolved now. */ - -auto inline void __attribute__ ((always_inline)) -elf_dynamic_do_Rel (struct link_map *map, - ElfW(Addr) reladdr, ElfW(Addr) relsize, - __typeof (((ElfW(Dyn) *) 0)->d_un.d_val) nrelative, - int lazy, int skip_ifunc) -{ - const ElfW(Rel) *r = (const void *) reladdr; - const ElfW(Rel) *end = (const void *) (reladdr + relsize); - ElfW(Addr) l_addr = map->l_addr; -# if defined ELF_MACHINE_IRELATIVE && !defined RTLD_BOOTSTRAP - const ElfW(Rel) *r2 = NULL; - const ElfW(Rel) *end2 = NULL; -# endif - -#if (!defined DO_RELA || !defined ELF_MACHINE_PLT_REL) && !defined RTLD_BOOTSTRAP - /* We never bind lazily during ld.so bootstrap. Unfortunately gcc is - not clever enough to see through all the function calls to realize - that. */ - if (lazy) - { - /* Doing lazy PLT relocations; they need very little info. */ - for (; r < end; ++r) -# ifdef ELF_MACHINE_IRELATIVE - if (ELFW(R_TYPE) (r->r_info) == ELF_MACHINE_IRELATIVE) - { - if (r2 == NULL) - r2 = r; - end2 = r; - } - else -# endif - elf_machine_lazy_rel (map, l_addr, r, skip_ifunc); - -# ifdef ELF_MACHINE_IRELATIVE - if (r2 != NULL) - for (; r2 <= end2; ++r2) - if (ELFW(R_TYPE) (r2->r_info) == ELF_MACHINE_IRELATIVE) - elf_machine_lazy_rel (map, l_addr, r2, skip_ifunc); -# endif - } - else -#endif - { - const ElfW(Sym) *const symtab = - (const void *) D_PTR (map, l_info[DT_SYMTAB]); - const ElfW(Rel) *relative = r; - r += nrelative; - -#ifndef RTLD_BOOTSTRAP - /* This is defined in rtld.c, but nowhere in the static libc.a; make - the reference weak so static programs can still link. This - declaration cannot be done when compiling rtld.c (i.e. #ifdef - RTLD_BOOTSTRAP) because rtld.c contains the common defn for - _dl_rtld_map, which is incompatible with a weak decl in the same - file. */ -# ifndef SHARED - weak_extern (GL(dl_rtld_map)); -# endif - if (map != &GL(dl_rtld_map)) /* Already done in rtld itself. */ -# if !defined DO_RELA || defined ELF_MACHINE_REL_RELATIVE - /* Rela platforms get the offset from r_addend and this must - be copied in the relocation address. Therefore we can skip - the relative relocations only if this is for rel - relocations or rela relocations if they are computed as - memory_loc += l_addr... */ - if (l_addr != 0) -# else - /* ...or we know the object has been prelinked. */ - if (l_addr != 0 || ! map->l_info[VALIDX(DT_GNU_PRELINKED)]) -# endif -#endif - for (; relative < r; ++relative) - DO_ELF_MACHINE_REL_RELATIVE (map, l_addr, relative); - -#ifdef RTLD_BOOTSTRAP - /* The dynamic linker always uses versioning. */ - assert (map->l_info[VERSYMIDX (DT_VERSYM)] != NULL); -#else - if (map->l_info[VERSYMIDX (DT_VERSYM)]) -#endif - { - const ElfW(Half) *const version = - (const void *) D_PTR (map, l_info[VERSYMIDX (DT_VERSYM)]); - - for (; r < end; ++r) - { -#if defined ELF_MACHINE_IRELATIVE && !defined RTLD_BOOTSTRAP - if (ELFW(R_TYPE) (r->r_info) == ELF_MACHINE_IRELATIVE) - { - if (r2 == NULL) - r2 = r; - end2 = r; - continue; - } -#endif - - ElfW(Half) ndx = version[ELFW(R_SYM) (r->r_info)] & 0x7fff; - elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)], - &map->l_versions[ndx], - (void *) (l_addr + r->r_offset), skip_ifunc); - } - -#if defined ELF_MACHINE_IRELATIVE && !defined RTLD_BOOTSTRAP - if (r2 != NULL) - for (; r2 <= end2; ++r2) - if (ELFW(R_TYPE) (r2->r_info) == ELF_MACHINE_IRELATIVE) - { - ElfW(Half) ndx - = version[ELFW(R_SYM) (r2->r_info)] & 0x7fff; - elf_machine_rel (map, r2, - &symtab[ELFW(R_SYM) (r2->r_info)], - &map->l_versions[ndx], - (void *) (l_addr + r2->r_offset), - skip_ifunc); - } -#endif - } -#ifndef RTLD_BOOTSTRAP - else - { - for (; r < end; ++r) -# ifdef ELF_MACHINE_IRELATIVE - if (ELFW(R_TYPE) (r->r_info) == ELF_MACHINE_IRELATIVE) - { - if (r2 == NULL) - r2 = r; - end2 = r; - } - else -# endif - elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)], NULL, - (void *) (l_addr + r->r_offset), skip_ifunc); - -# ifdef ELF_MACHINE_IRELATIVE - if (r2 != NULL) - for (; r2 <= end2; ++r2) - if (ELFW(R_TYPE) (r2->r_info) == ELF_MACHINE_IRELATIVE) - elf_machine_rel (map, r2, &symtab[ELFW(R_SYM) (r2->r_info)], - NULL, (void *) (l_addr + r2->r_offset), - skip_ifunc); -# endif - } -#endif - } -} - -#undef elf_dynamic_do_Rel -#undef Rel -#undef elf_machine_rel -#undef elf_machine_rel_relative -#undef DO_ELF_MACHINE_REL_RELATIVE -#undef DO_RELA diff --git a/elf/dynamic-link.h b/elf/dynamic-link.h deleted file mode 100644 index 60f2d91151..0000000000 --- a/elf/dynamic-link.h +++ /dev/null @@ -1,203 +0,0 @@ -/* Inline functions for dynamic linking. - Copyright (C) 1995-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -/* This macro is used as a callback from elf_machine_rel{a,} when a - static TLS reloc is about to be performed. Since (in dl-load.c) we - permit dynamic loading of objects that might use such relocs, we - have to check whether each use is actually doable. If the object - whose TLS segment the reference resolves to was allocated space in - the static TLS block at startup, then it's ok. Otherwise, we make - 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 (!HAVE_STATIC_TLS (map, sym_map)) \ - _dl_allocate_static_tls (sym_map); \ - } while (0) - -#define TRY_STATIC_TLS(map, sym_map) \ - (__builtin_expect ((sym_map)->l_tls_offset \ - != FORCED_DYNAMIC_TLS_OFFSET, 1) \ - && (__builtin_expect ((sym_map)->l_tls_offset != NO_TLS_OFFSET, 1) \ - || _dl_try_allocate_static_tls (sym_map) == 0)) - -int internal_function attribute_hidden - _dl_try_allocate_static_tls (struct link_map *map); - -#include <elf.h> - -#ifdef RESOLVE_MAP -/* We pass reloc_addr as a pointer to void, as opposed to a pointer to - ElfW(Addr), because not all architectures can assume that the - relocated address is properly aligned, whereas the compiler is - entitled to assume that a pointer to a type is properly aligned for - the type. Even if we cast the pointer back to some other type with - less strict alignment requirements, the compiler might still - remember that the pointer was originally more aligned, thereby - optimizing away alignment tests or using word instructions for - copying memory, breaking the very code written to handle the - unaligned cases. */ -# if ! ELF_MACHINE_NO_REL -auto inline void __attribute__((always_inline)) -elf_machine_rel (struct link_map *map, const ElfW(Rel) *reloc, - const ElfW(Sym) *sym, const struct r_found_version *version, - void *const reloc_addr, int skip_ifunc); -auto inline void __attribute__((always_inline)) -elf_machine_rel_relative (ElfW(Addr) l_addr, const ElfW(Rel) *reloc, - void *const reloc_addr); -# endif -# if ! ELF_MACHINE_NO_RELA -auto inline void __attribute__((always_inline)) -elf_machine_rela (struct link_map *map, const ElfW(Rela) *reloc, - const ElfW(Sym) *sym, const struct r_found_version *version, - void *const reloc_addr, int skip_ifunc); -auto inline void __attribute__((always_inline)) -elf_machine_rela_relative (ElfW(Addr) l_addr, const ElfW(Rela) *reloc, - void *const reloc_addr); -# endif -# if ELF_MACHINE_NO_RELA || defined ELF_MACHINE_PLT_REL -auto inline void __attribute__((always_inline)) -elf_machine_lazy_rel (struct link_map *map, - ElfW(Addr) l_addr, const ElfW(Rel) *reloc, - int skip_ifunc); -# else -auto inline void __attribute__((always_inline)) -elf_machine_lazy_rel (struct link_map *map, - ElfW(Addr) l_addr, const ElfW(Rela) *reloc, - int skip_ifunc); -# endif -#endif - -#include <dl-machine.h> - -#include "get-dynamic-info.h" - -#ifdef RESOLVE_MAP - -# ifdef RTLD_BOOTSTRAP -# define ELF_DURING_STARTUP (1) -# else -# define ELF_DURING_STARTUP (0) -# endif - -/* Get the definitions of `elf_dynamic_do_rel' and `elf_dynamic_do_rela'. - These functions are almost identical, so we use cpp magic to avoid - duplicating their code. It cannot be done in a more general function - because we must be able to completely inline. */ - -/* On some machines, notably SPARC, DT_REL* includes DT_JMPREL in its - range. Note that according to the ELF spec, this is completely legal! - - We are guarenteed that we have one of three situations. Either DT_JMPREL - comes immediately after DT_REL*, or there is overlap and DT_JMPREL - consumes precisely the very end of the DT_REL*, or DT_JMPREL and DT_REL* - are completely separate and there is a gap between them. */ - -# define _ELF_DYNAMIC_DO_RELOC(RELOC, reloc, map, do_lazy, skip_ifunc, test_rel) \ - do { \ - struct { ElfW(Addr) start, size; \ - __typeof (((ElfW(Dyn) *) 0)->d_un.d_val) nrelative; int lazy; } \ - ranges[2] = { { 0, 0, 0, 0 }, { 0, 0, 0, 0 } }; \ - \ - if ((map)->l_info[DT_##RELOC]) \ - { \ - ranges[0].start = D_PTR ((map), l_info[DT_##RELOC]); \ - 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 \ - = 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)) \ - { \ - ElfW(Addr) start = D_PTR ((map), l_info[DT_JMPREL]); \ - ElfW(Addr) size = (map)->l_info[DT_PLTRELSZ]->d_un.d_val; \ - \ - if (ranges[0].start + ranges[0].size == (start + size)) \ - ranges[0].size -= size; \ - if (ELF_DURING_STARTUP \ - || (!(do_lazy) \ - && (ranges[0].start + ranges[0].size) == start)) \ - { \ - /* Combine processing the sections. */ \ - ranges[0].size += size; \ - } \ - else \ - { \ - ranges[1].start = start; \ - ranges[1].size = size; \ - ranges[1].lazy = (do_lazy); \ - } \ - } \ - \ - if (ELF_DURING_STARTUP) \ - elf_dynamic_do_##reloc ((map), ranges[0].start, ranges[0].size, \ - ranges[0].nrelative, 0, skip_ifunc); \ - else \ - { \ - int ranges_index; \ - for (ranges_index = 0; ranges_index < 2; ++ranges_index) \ - elf_dynamic_do_##reloc ((map), \ - ranges[ranges_index].start, \ - ranges[ranges_index].size, \ - ranges[ranges_index].nrelative, \ - ranges[ranges_index].lazy, \ - skip_ifunc); \ - } \ - } while (0) - -# if ELF_MACHINE_NO_REL || ELF_MACHINE_NO_RELA -# define _ELF_CHECK_REL 0 -# else -# define _ELF_CHECK_REL 1 -# endif - -# if ! ELF_MACHINE_NO_REL -# include "do-rel.h" -# define ELF_DYNAMIC_DO_REL(map, lazy, skip_ifunc) \ - _ELF_DYNAMIC_DO_RELOC (REL, Rel, map, lazy, skip_ifunc, _ELF_CHECK_REL) -# else -# define ELF_DYNAMIC_DO_REL(map, lazy, skip_ifunc) /* Nothing to do. */ -# endif - -# if ! ELF_MACHINE_NO_RELA -# define DO_RELA -# include "do-rel.h" -# define ELF_DYNAMIC_DO_RELA(map, lazy, skip_ifunc) \ - _ELF_DYNAMIC_DO_RELOC (RELA, Rela, map, lazy, skip_ifunc, _ELF_CHECK_REL) -# else -# define ELF_DYNAMIC_DO_RELA(map, lazy, skip_ifunc) /* Nothing to do. */ -# endif - -/* This can't just be an inline function because GCC is too dumb - to inline functions containing inlines themselves. */ -# define ELF_DYNAMIC_RELOCATE(map, lazy, consider_profile, skip_ifunc) \ - do { \ - int edr_lazy = elf_machine_runtime_setup ((map), (lazy), \ - (consider_profile)); \ - ELF_DYNAMIC_DO_REL ((map), edr_lazy, skip_ifunc); \ - ELF_DYNAMIC_DO_RELA ((map), edr_lazy, skip_ifunc); \ - } while (0) - -#endif diff --git a/elf/elf.h b/elf/elf.h deleted file mode 100644 index fff893d433..0000000000 --- a/elf/elf.h +++ /dev/null @@ -1,3761 +0,0 @@ -/* This file defines standard ELF types, structures, and macros. - Copyright (C) 1995-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -#ifndef _ELF_H -#define _ELF_H 1 - -#include <features.h> - -__BEGIN_DECLS - -/* Standard ELF types. */ - -#include <stdint.h> - -/* Type for a 16-bit quantity. */ -typedef uint16_t Elf32_Half; -typedef uint16_t Elf64_Half; - -/* Types for signed and unsigned 32-bit quantities. */ -typedef uint32_t Elf32_Word; -typedef int32_t Elf32_Sword; -typedef uint32_t Elf64_Word; -typedef int32_t Elf64_Sword; - -/* Types for signed and unsigned 64-bit quantities. */ -typedef uint64_t Elf32_Xword; -typedef int64_t Elf32_Sxword; -typedef uint64_t Elf64_Xword; -typedef int64_t Elf64_Sxword; - -/* Type of addresses. */ -typedef uint32_t Elf32_Addr; -typedef uint64_t Elf64_Addr; - -/* Type of file offsets. */ -typedef uint32_t Elf32_Off; -typedef uint64_t Elf64_Off; - -/* Type for section indices, which are 16-bit quantities. */ -typedef uint16_t Elf32_Section; -typedef uint16_t Elf64_Section; - -/* Type for version symbol information. */ -typedef Elf32_Half Elf32_Versym; -typedef Elf64_Half Elf64_Versym; - - -/* The ELF file header. This appears at the start of every ELF file. */ - -#define EI_NIDENT (16) - -typedef struct -{ - unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */ - Elf32_Half e_type; /* Object file type */ - Elf32_Half e_machine; /* Architecture */ - Elf32_Word e_version; /* Object file version */ - Elf32_Addr e_entry; /* Entry point virtual address */ - Elf32_Off e_phoff; /* Program header table file offset */ - Elf32_Off e_shoff; /* Section header table file offset */ - Elf32_Word e_flags; /* Processor-specific flags */ - Elf32_Half e_ehsize; /* ELF header size in bytes */ - Elf32_Half e_phentsize; /* Program header table entry size */ - Elf32_Half e_phnum; /* Program header table entry count */ - Elf32_Half e_shentsize; /* Section header table entry size */ - Elf32_Half e_shnum; /* Section header table entry count */ - Elf32_Half e_shstrndx; /* Section header string table index */ -} Elf32_Ehdr; - -typedef struct -{ - unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */ - Elf64_Half e_type; /* Object file type */ - Elf64_Half e_machine; /* Architecture */ - Elf64_Word e_version; /* Object file version */ - Elf64_Addr e_entry; /* Entry point virtual address */ - Elf64_Off e_phoff; /* Program header table file offset */ - Elf64_Off e_shoff; /* Section header table file offset */ - Elf64_Word e_flags; /* Processor-specific flags */ - Elf64_Half e_ehsize; /* ELF header size in bytes */ - Elf64_Half e_phentsize; /* Program header table entry size */ - Elf64_Half e_phnum; /* Program header table entry count */ - Elf64_Half e_shentsize; /* Section header table entry size */ - Elf64_Half e_shnum; /* Section header table entry count */ - Elf64_Half e_shstrndx; /* Section header string table index */ -} Elf64_Ehdr; - -/* Fields in the e_ident array. The EI_* macros are indices into the - array. The macros under each EI_* macro are the values the byte - may have. */ - -#define EI_MAG0 0 /* File identification byte 0 index */ -#define ELFMAG0 0x7f /* Magic number byte 0 */ - -#define EI_MAG1 1 /* File identification byte 1 index */ -#define ELFMAG1 'E' /* Magic number byte 1 */ - -#define EI_MAG2 2 /* File identification byte 2 index */ -#define ELFMAG2 'L' /* Magic number byte 2 */ - -#define EI_MAG3 3 /* File identification byte 3 index */ -#define ELFMAG3 'F' /* Magic number byte 3 */ - -/* Conglomeration of the identification bytes, for easy testing as a word. */ -#define ELFMAG "\177ELF" -#define SELFMAG 4 - -#define EI_CLASS 4 /* File class byte index */ -#define ELFCLASSNONE 0 /* Invalid class */ -#define ELFCLASS32 1 /* 32-bit objects */ -#define ELFCLASS64 2 /* 64-bit objects */ -#define ELFCLASSNUM 3 - -#define EI_DATA 5 /* Data encoding byte index */ -#define ELFDATANONE 0 /* Invalid data encoding */ -#define ELFDATA2LSB 1 /* 2's complement, little endian */ -#define ELFDATA2MSB 2 /* 2's complement, big endian */ -#define ELFDATANUM 3 - -#define EI_VERSION 6 /* File version byte index */ - /* Value must be EV_CURRENT */ - -#define EI_OSABI 7 /* OS ABI identification */ -#define ELFOSABI_NONE 0 /* UNIX System V ABI */ -#define ELFOSABI_SYSV 0 /* Alias. */ -#define ELFOSABI_HPUX 1 /* HP-UX */ -#define ELFOSABI_NETBSD 2 /* NetBSD. */ -#define ELFOSABI_GNU 3 /* Object uses GNU ELF extensions. */ -#define ELFOSABI_LINUX ELFOSABI_GNU /* Compatibility alias. */ -#define ELFOSABI_SOLARIS 6 /* Sun Solaris. */ -#define ELFOSABI_AIX 7 /* IBM AIX. */ -#define ELFOSABI_IRIX 8 /* SGI Irix. */ -#define ELFOSABI_FREEBSD 9 /* FreeBSD. */ -#define ELFOSABI_TRU64 10 /* Compaq TRU64 UNIX. */ -#define ELFOSABI_MODESTO 11 /* Novell Modesto. */ -#define ELFOSABI_OPENBSD 12 /* OpenBSD. */ -#define ELFOSABI_ARM_AEABI 64 /* ARM EABI */ -#define ELFOSABI_ARM 97 /* ARM */ -#define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */ - -#define EI_ABIVERSION 8 /* ABI version */ - -#define EI_PAD 9 /* Byte index of padding bytes */ - -/* Legal values for e_type (object file type). */ - -#define ET_NONE 0 /* No file type */ -#define ET_REL 1 /* Relocatable file */ -#define ET_EXEC 2 /* Executable file */ -#define ET_DYN 3 /* Shared object file */ -#define ET_CORE 4 /* Core file */ -#define ET_NUM 5 /* Number of defined types */ -#define ET_LOOS 0xfe00 /* OS-specific range start */ -#define ET_HIOS 0xfeff /* OS-specific range end */ -#define ET_LOPROC 0xff00 /* Processor-specific range start */ -#define ET_HIPROC 0xffff /* Processor-specific range end */ - -/* Legal values for e_machine (architecture). */ - -#define EM_NONE 0 /* No machine */ -#define EM_M32 1 /* AT&T WE 32100 */ -#define EM_SPARC 2 /* SUN SPARC */ -#define EM_386 3 /* Intel 80386 */ -#define EM_68K 4 /* Motorola m68k family */ -#define EM_88K 5 /* Motorola m88k family */ -#define EM_IAMCU 6 /* Intel MCU */ -#define EM_860 7 /* Intel 80860 */ -#define EM_MIPS 8 /* MIPS R3000 big-endian */ -#define EM_S370 9 /* IBM System/370 */ -#define EM_MIPS_RS3_LE 10 /* MIPS R3000 little-endian */ - /* reserved 11-14 */ -#define EM_PARISC 15 /* HPPA */ - /* reserved 16 */ -#define EM_VPP500 17 /* Fujitsu VPP500 */ -#define EM_SPARC32PLUS 18 /* Sun's "v8plus" */ -#define EM_960 19 /* Intel 80960 */ -#define EM_PPC 20 /* PowerPC */ -#define EM_PPC64 21 /* PowerPC 64-bit */ -#define EM_S390 22 /* IBM S390 */ -#define EM_SPU 23 /* IBM SPU/SPC */ - /* reserved 24-35 */ -#define EM_V800 36 /* NEC V800 series */ -#define EM_FR20 37 /* Fujitsu FR20 */ -#define EM_RH32 38 /* TRW RH-32 */ -#define EM_RCE 39 /* Motorola RCE */ -#define EM_ARM 40 /* ARM */ -#define EM_FAKE_ALPHA 41 /* Digital Alpha */ -#define EM_SH 42 /* Hitachi SH */ -#define EM_SPARCV9 43 /* SPARC v9 64-bit */ -#define EM_TRICORE 44 /* Siemens Tricore */ -#define EM_ARC 45 /* Argonaut RISC Core */ -#define EM_H8_300 46 /* Hitachi H8/300 */ -#define EM_H8_300H 47 /* Hitachi H8/300H */ -#define EM_H8S 48 /* Hitachi H8S */ -#define EM_H8_500 49 /* Hitachi H8/500 */ -#define EM_IA_64 50 /* Intel Merced */ -#define EM_MIPS_X 51 /* Stanford MIPS-X */ -#define EM_COLDFIRE 52 /* Motorola Coldfire */ -#define EM_68HC12 53 /* Motorola M68HC12 */ -#define EM_MMA 54 /* Fujitsu MMA Multimedia Accelerator */ -#define EM_PCP 55 /* Siemens PCP */ -#define EM_NCPU 56 /* Sony nCPU embeeded RISC */ -#define EM_NDR1 57 /* Denso NDR1 microprocessor */ -#define EM_STARCORE 58 /* Motorola Start*Core processor */ -#define EM_ME16 59 /* Toyota ME16 processor */ -#define EM_ST100 60 /* STMicroelectronic ST100 processor */ -#define EM_TINYJ 61 /* Advanced Logic Corp. Tinyj emb.fam */ -#define EM_X86_64 62 /* AMD x86-64 architecture */ -#define EM_PDSP 63 /* Sony DSP Processor */ -#define EM_PDP10 64 /* Digital PDP-10 */ -#define EM_PDP11 65 /* Digital PDP-11 */ -#define EM_FX66 66 /* Siemens FX66 microcontroller */ -#define EM_ST9PLUS 67 /* STMicroelectronics ST9+ 8/16 mc */ -#define EM_ST7 68 /* STmicroelectronics ST7 8 bit mc */ -#define EM_68HC16 69 /* Motorola MC68HC16 microcontroller */ -#define EM_68HC11 70 /* Motorola MC68HC11 microcontroller */ -#define EM_68HC08 71 /* Motorola MC68HC08 microcontroller */ -#define EM_68HC05 72 /* Motorola MC68HC05 microcontroller */ -#define EM_SVX 73 /* Silicon Graphics SVx */ -#define EM_ST19 74 /* STMicroelectronics ST19 8 bit mc */ -#define EM_VAX 75 /* Digital VAX */ -#define EM_CRIS 76 /* Axis Communications 32-bit emb.proc */ -#define EM_JAVELIN 77 /* Infineon Technologies 32-bit emb.proc */ -#define EM_FIREPATH 78 /* Element 14 64-bit DSP Processor */ -#define EM_ZSP 79 /* LSI Logic 16-bit DSP Processor */ -#define EM_MMIX 80 /* Donald Knuth's educational 64-bit proc */ -#define EM_HUANY 81 /* Harvard University machine-independent object files */ -#define EM_PRISM 82 /* SiTera Prism */ -#define EM_AVR 83 /* Atmel AVR 8-bit microcontroller */ -#define EM_FR30 84 /* Fujitsu FR30 */ -#define EM_D10V 85 /* Mitsubishi D10V */ -#define EM_D30V 86 /* Mitsubishi D30V */ -#define EM_V850 87 /* NEC v850 */ -#define EM_M32R 88 /* Mitsubishi M32R */ -#define EM_MN10300 89 /* Matsushita MN10300 */ -#define EM_MN10200 90 /* Matsushita MN10200 */ -#define EM_PJ 91 /* picoJava */ -#define EM_OPENRISC 92 /* OpenRISC 32-bit embedded processor */ -#define EM_ARC_COMPACT 93 /* ARC International ARCompact */ -#define EM_XTENSA 94 /* Tensilica Xtensa Architecture */ -#define EM_VIDEOCORE 95 /* Alphamosaic VideoCore */ -#define EM_TMM_GPP 96 /* Thompson Multimedia General Purpose Proc */ -#define EM_NS32K 97 /* National Semi. 32000 */ -#define EM_TPC 98 /* Tenor Network TPC */ -#define EM_SNP1K 99 /* Trebia SNP 1000 */ -#define EM_ST200 100 /* STMicroelectronics ST200 */ -#define EM_IP2K 101 /* Ubicom IP2xxx */ -#define EM_MAX 102 /* MAX processor */ -#define EM_CR 103 /* National Semi. CompactRISC */ -#define EM_F2MC16 104 /* Fujitsu F2MC16 */ -#define EM_MSP430 105 /* Texas Instruments msp430 */ -#define EM_BLACKFIN 106 /* Analog Devices Blackfin DSP */ -#define EM_SE_C33 107 /* Seiko Epson S1C33 family */ -#define EM_SEP 108 /* Sharp embedded microprocessor */ -#define EM_ARCA 109 /* Arca RISC */ -#define EM_UNICORE 110 /* PKU-Unity & MPRC Peking Uni. mc series */ -#define EM_EXCESS 111 /* eXcess configurable cpu */ -#define EM_DXP 112 /* Icera Semi. Deep Execution Processor */ -#define EM_ALTERA_NIOS2 113 /* Altera Nios II */ -#define EM_CRX 114 /* National Semi. CompactRISC CRX */ -#define EM_XGATE 115 /* Motorola XGATE */ -#define EM_C166 116 /* Infineon C16x/XC16x */ -#define EM_M16C 117 /* Renesas M16C */ -#define EM_DSPIC30F 118 /* Microchip Technology dsPIC30F */ -#define EM_CE 119 /* Freescale Communication Engine RISC */ -#define EM_M32C 120 /* Renesas M32C */ - /* reserved 121-130 */ -#define EM_TSK3000 131 /* Altium TSK3000 */ -#define EM_RS08 132 /* Freescale RS08 */ -#define EM_SHARC 133 /* Analog Devices SHARC family */ -#define EM_ECOG2 134 /* Cyan Technology eCOG2 */ -#define EM_SCORE7 135 /* Sunplus S+core7 RISC */ -#define EM_DSP24 136 /* New Japan Radio (NJR) 24-bit DSP */ -#define EM_VIDEOCORE3 137 /* Broadcom VideoCore III */ -#define EM_LATTICEMICO32 138 /* RISC for Lattice FPGA */ -#define EM_SE_C17 139 /* Seiko Epson C17 */ -#define EM_TI_C6000 140 /* Texas Instruments TMS320C6000 DSP */ -#define EM_TI_C2000 141 /* Texas Instruments TMS320C2000 DSP */ -#define EM_TI_C5500 142 /* Texas Instruments TMS320C55x DSP */ -#define EM_TI_ARP32 143 /* Texas Instruments App. Specific RISC */ -#define EM_TI_PRU 144 /* Texas Instruments Prog. Realtime Unit */ - /* reserved 145-159 */ -#define EM_MMDSP_PLUS 160 /* STMicroelectronics 64bit VLIW DSP */ -#define EM_CYPRESS_M8C 161 /* Cypress M8C */ -#define EM_R32C 162 /* Renesas R32C */ -#define EM_TRIMEDIA 163 /* NXP Semi. TriMedia */ -#define EM_QDSP6 164 /* QUALCOMM DSP6 */ -#define EM_8051 165 /* Intel 8051 and variants */ -#define EM_STXP7X 166 /* STMicroelectronics STxP7x */ -#define EM_NDS32 167 /* Andes Tech. compact code emb. RISC */ -#define EM_ECOG1X 168 /* Cyan Technology eCOG1X */ -#define EM_MAXQ30 169 /* Dallas Semi. MAXQ30 mc */ -#define EM_XIMO16 170 /* New Japan Radio (NJR) 16-bit DSP */ -#define EM_MANIK 171 /* M2000 Reconfigurable RISC */ -#define EM_CRAYNV2 172 /* Cray NV2 vector architecture */ -#define EM_RX 173 /* Renesas RX */ -#define EM_METAG 174 /* Imagination Tech. META */ -#define EM_MCST_ELBRUS 175 /* MCST Elbrus */ -#define EM_ECOG16 176 /* Cyan Technology eCOG16 */ -#define EM_CR16 177 /* National Semi. CompactRISC CR16 */ -#define EM_ETPU 178 /* Freescale Extended Time Processing Unit */ -#define EM_SLE9X 179 /* Infineon Tech. SLE9X */ -#define EM_L10M 180 /* Intel L10M */ -#define EM_K10M 181 /* Intel K10M */ - /* reserved 182 */ -#define EM_AARCH64 183 /* ARM AARCH64 */ - /* reserved 184 */ -#define EM_AVR32 185 /* Amtel 32-bit microprocessor */ -#define EM_STM8 186 /* STMicroelectronics STM8 */ -#define EM_TILE64 187 /* Tileta TILE64 */ -#define EM_TILEPRO 188 /* Tilera TILEPro */ -#define EM_MICROBLAZE 189 /* Xilinx MicroBlaze */ -#define EM_CUDA 190 /* NVIDIA CUDA */ -#define EM_TILEGX 191 /* Tilera TILE-Gx */ -#define EM_CLOUDSHIELD 192 /* CloudShield */ -#define EM_COREA_1ST 193 /* KIPO-KAIST Core-A 1st gen. */ -#define EM_COREA_2ND 194 /* KIPO-KAIST Core-A 2nd gen. */ -#define EM_ARC_COMPACT2 195 /* Synopsys ARCompact V2 */ -#define EM_OPEN8 196 /* Open8 RISC */ -#define EM_RL78 197 /* Renesas RL78 */ -#define EM_VIDEOCORE5 198 /* Broadcom VideoCore V */ -#define EM_78KOR 199 /* Renesas 78KOR */ -#define EM_56800EX 200 /* Freescale 56800EX DSC */ -#define EM_BA1 201 /* Beyond BA1 */ -#define EM_BA2 202 /* Beyond BA2 */ -#define EM_XCORE 203 /* XMOS xCORE */ -#define EM_MCHP_PIC 204 /* Microchip 8-bit PIC(r) */ - /* reserved 205-209 */ -#define EM_KM32 210 /* KM211 KM32 */ -#define EM_KMX32 211 /* KM211 KMX32 */ -#define EM_EMX16 212 /* KM211 KMX16 */ -#define EM_EMX8 213 /* KM211 KMX8 */ -#define EM_KVARC 214 /* KM211 KVARC */ -#define EM_CDP 215 /* Paneve CDP */ -#define EM_COGE 216 /* Cognitive Smart Memory Processor */ -#define EM_COOL 217 /* Bluechip CoolEngine */ -#define EM_NORC 218 /* Nanoradio Optimized RISC */ -#define EM_CSR_KALIMBA 219 /* CSR Kalimba */ -#define EM_Z80 220 /* Zilog Z80 */ -#define EM_VISIUM 221 /* Controls and Data Services VISIUMcore */ -#define EM_FT32 222 /* FTDI Chip FT32 */ -#define EM_MOXIE 223 /* Moxie processor */ -#define EM_AMDGPU 224 /* AMD GPU */ - /* reserved 225-242 */ -#define EM_RISCV 243 /* RISC-V */ - -#define EM_BPF 247 /* Linux BPF -- in-kernel virtual machine */ - -#define EM_NUM 248 - -/* Old spellings/synonyms. */ - -#define EM_ARC_A5 EM_ARC_COMPACT - -/* If it is necessary to assign new unofficial EM_* values, please - pick large random numbers (0x8523, 0xa7f2, etc.) to minimize the - chances of collision with official or non-GNU unofficial values. */ - -#define EM_ALPHA 0x9026 - -/* Legal values for e_version (version). */ - -#define EV_NONE 0 /* Invalid ELF version */ -#define EV_CURRENT 1 /* Current version */ -#define EV_NUM 2 - -/* Section header. */ - -typedef struct -{ - Elf32_Word sh_name; /* Section name (string tbl index) */ - Elf32_Word sh_type; /* Section type */ - Elf32_Word sh_flags; /* Section flags */ - Elf32_Addr sh_addr; /* Section virtual addr at execution */ - Elf32_Off sh_offset; /* Section file offset */ - Elf32_Word sh_size; /* Section size in bytes */ - Elf32_Word sh_link; /* Link to another section */ - Elf32_Word sh_info; /* Additional section information */ - Elf32_Word sh_addralign; /* Section alignment */ - Elf32_Word sh_entsize; /* Entry size if section holds table */ -} Elf32_Shdr; - -typedef struct -{ - Elf64_Word sh_name; /* Section name (string tbl index) */ - Elf64_Word sh_type; /* Section type */ - Elf64_Xword sh_flags; /* Section flags */ - Elf64_Addr sh_addr; /* Section virtual addr at execution */ - Elf64_Off sh_offset; /* Section file offset */ - Elf64_Xword sh_size; /* Section size in bytes */ - Elf64_Word sh_link; /* Link to another section */ - Elf64_Word sh_info; /* Additional section information */ - Elf64_Xword sh_addralign; /* Section alignment */ - Elf64_Xword sh_entsize; /* Entry size if section holds table */ -} Elf64_Shdr; - -/* Special section indices. */ - -#define SHN_UNDEF 0 /* Undefined section */ -#define SHN_LORESERVE 0xff00 /* Start of reserved indices */ -#define SHN_LOPROC 0xff00 /* Start of processor-specific */ -#define SHN_BEFORE 0xff00 /* Order section before all others - (Solaris). */ -#define SHN_AFTER 0xff01 /* Order section after all others - (Solaris). */ -#define SHN_HIPROC 0xff1f /* End of processor-specific */ -#define SHN_LOOS 0xff20 /* Start of OS-specific */ -#define SHN_HIOS 0xff3f /* End of OS-specific */ -#define SHN_ABS 0xfff1 /* Associated symbol is absolute */ -#define SHN_COMMON 0xfff2 /* Associated symbol is common */ -#define SHN_XINDEX 0xffff /* Index is in extra table. */ -#define SHN_HIRESERVE 0xffff /* End of reserved indices */ - -/* Legal values for sh_type (section type). */ - -#define SHT_NULL 0 /* Section header table entry unused */ -#define SHT_PROGBITS 1 /* Program data */ -#define SHT_SYMTAB 2 /* Symbol table */ -#define SHT_STRTAB 3 /* String table */ -#define SHT_RELA 4 /* Relocation entries with addends */ -#define SHT_HASH 5 /* Symbol hash table */ -#define SHT_DYNAMIC 6 /* Dynamic linking information */ -#define SHT_NOTE 7 /* Notes */ -#define SHT_NOBITS 8 /* Program space with no data (bss) */ -#define SHT_REL 9 /* Relocation entries, no addends */ -#define SHT_SHLIB 10 /* Reserved */ -#define SHT_DYNSYM 11 /* Dynamic linker symbol table */ -#define SHT_INIT_ARRAY 14 /* Array of constructors */ -#define SHT_FINI_ARRAY 15 /* Array of destructors */ -#define SHT_PREINIT_ARRAY 16 /* Array of pre-constructors */ -#define SHT_GROUP 17 /* Section group */ -#define SHT_SYMTAB_SHNDX 18 /* Extended section indeces */ -#define SHT_NUM 19 /* Number of defined types. */ -#define SHT_LOOS 0x60000000 /* Start OS-specific. */ -#define SHT_GNU_ATTRIBUTES 0x6ffffff5 /* Object attributes. */ -#define SHT_GNU_HASH 0x6ffffff6 /* GNU-style hash table. */ -#define SHT_GNU_LIBLIST 0x6ffffff7 /* Prelink library list */ -#define SHT_CHECKSUM 0x6ffffff8 /* Checksum for DSO content. */ -#define SHT_LOSUNW 0x6ffffffa /* Sun-specific low bound. */ -#define SHT_SUNW_move 0x6ffffffa -#define SHT_SUNW_COMDAT 0x6ffffffb -#define SHT_SUNW_syminfo 0x6ffffffc -#define SHT_GNU_verdef 0x6ffffffd /* Version definition section. */ -#define SHT_GNU_verneed 0x6ffffffe /* Version needs section. */ -#define SHT_GNU_versym 0x6fffffff /* Version symbol table. */ -#define SHT_HISUNW 0x6fffffff /* Sun-specific high bound. */ -#define SHT_HIOS 0x6fffffff /* End OS-specific type */ -#define SHT_LOPROC 0x70000000 /* Start of processor-specific */ -#define SHT_HIPROC 0x7fffffff /* End of processor-specific */ -#define SHT_LOUSER 0x80000000 /* Start of application-specific */ -#define SHT_HIUSER 0x8fffffff /* End of application-specific */ - -/* Legal values for sh_flags (section flags). */ - -#define SHF_WRITE (1 << 0) /* Writable */ -#define SHF_ALLOC (1 << 1) /* Occupies memory during execution */ -#define SHF_EXECINSTR (1 << 2) /* Executable */ -#define SHF_MERGE (1 << 4) /* Might be merged */ -#define SHF_STRINGS (1 << 5) /* Contains nul-terminated strings */ -#define SHF_INFO_LINK (1 << 6) /* `sh_info' contains SHT index */ -#define SHF_LINK_ORDER (1 << 7) /* Preserve order after combining */ -#define SHF_OS_NONCONFORMING (1 << 8) /* Non-standard OS specific handling - 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 (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. */ - -/* Symbol table entry. */ - -typedef struct -{ - Elf32_Word st_name; /* Symbol name (string tbl index) */ - Elf32_Addr st_value; /* Symbol value */ - Elf32_Word st_size; /* Symbol size */ - unsigned char st_info; /* Symbol type and binding */ - unsigned char st_other; /* Symbol visibility */ - Elf32_Section st_shndx; /* Section index */ -} Elf32_Sym; - -typedef struct -{ - Elf64_Word st_name; /* Symbol name (string tbl index) */ - unsigned char st_info; /* Symbol type and binding */ - unsigned char st_other; /* Symbol visibility */ - Elf64_Section st_shndx; /* Section index */ - Elf64_Addr st_value; /* Symbol value */ - Elf64_Xword st_size; /* Symbol size */ -} Elf64_Sym; - -/* The syminfo section if available contains additional information about - every dynamic symbol. */ - -typedef struct -{ - Elf32_Half si_boundto; /* Direct bindings, symbol bound to */ - Elf32_Half si_flags; /* Per symbol flags */ -} Elf32_Syminfo; - -typedef struct -{ - Elf64_Half si_boundto; /* Direct bindings, symbol bound to */ - Elf64_Half si_flags; /* Per symbol flags */ -} Elf64_Syminfo; - -/* Possible values for si_boundto. */ -#define SYMINFO_BT_SELF 0xffff /* Symbol bound to self */ -#define SYMINFO_BT_PARENT 0xfffe /* Symbol bound to parent */ -#define SYMINFO_BT_LOWRESERVE 0xff00 /* Beginning of reserved entries */ - -/* Possible bitmasks for si_flags. */ -#define SYMINFO_FLG_DIRECT 0x0001 /* Direct bound symbol */ -#define SYMINFO_FLG_PASSTHRU 0x0002 /* Pass-thru symbol for translator */ -#define SYMINFO_FLG_COPY 0x0004 /* Symbol is a copy-reloc */ -#define SYMINFO_FLG_LAZYLOAD 0x0008 /* Symbol bound to object to be lazy - loaded */ -/* Syminfo version values. */ -#define SYMINFO_NONE 0 -#define SYMINFO_CURRENT 1 -#define SYMINFO_NUM 2 - - -/* How to extract and insert information held in the st_info field. */ - -#define ELF32_ST_BIND(val) (((unsigned char) (val)) >> 4) -#define ELF32_ST_TYPE(val) ((val) & 0xf) -#define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf)) - -/* Both Elf32_Sym and Elf64_Sym use the same one-byte st_info field. */ -#define ELF64_ST_BIND(val) ELF32_ST_BIND (val) -#define ELF64_ST_TYPE(val) ELF32_ST_TYPE (val) -#define ELF64_ST_INFO(bind, type) ELF32_ST_INFO ((bind), (type)) - -/* Legal values for ST_BIND subfield of st_info (symbol binding). */ - -#define STB_LOCAL 0 /* Local symbol */ -#define STB_GLOBAL 1 /* Global symbol */ -#define STB_WEAK 2 /* Weak symbol */ -#define STB_NUM 3 /* Number of defined types. */ -#define STB_LOOS 10 /* Start of OS-specific */ -#define STB_GNU_UNIQUE 10 /* Unique symbol. */ -#define STB_HIOS 12 /* End of OS-specific */ -#define STB_LOPROC 13 /* Start of processor-specific */ -#define STB_HIPROC 15 /* End of processor-specific */ - -/* Legal values for ST_TYPE subfield of st_info (symbol type). */ - -#define STT_NOTYPE 0 /* Symbol type is unspecified */ -#define STT_OBJECT 1 /* Symbol is a data object */ -#define STT_FUNC 2 /* Symbol is a code object */ -#define STT_SECTION 3 /* Symbol associated with a section */ -#define STT_FILE 4 /* Symbol's name is file name */ -#define STT_COMMON 5 /* Symbol is a common data object */ -#define STT_TLS 6 /* Symbol is thread-local data object*/ -#define STT_NUM 7 /* Number of defined types. */ -#define STT_LOOS 10 /* Start of OS-specific */ -#define STT_GNU_IFUNC 10 /* Symbol is indirect code object */ -#define STT_HIOS 12 /* End of OS-specific */ -#define STT_LOPROC 13 /* Start of processor-specific */ -#define STT_HIPROC 15 /* End of processor-specific */ - - -/* Symbol table indices are found in the hash buckets and chain table - of a symbol hash table section. This special index value indicates - the end of a chain, meaning no further symbols are found in that bucket. */ - -#define STN_UNDEF 0 /* End of a chain. */ - - -/* How to extract and insert information held in the st_other field. */ - -#define ELF32_ST_VISIBILITY(o) ((o) & 0x03) - -/* For ELF64 the definitions are the same. */ -#define ELF64_ST_VISIBILITY(o) ELF32_ST_VISIBILITY (o) - -/* Symbol visibility specification encoded in the st_other field. */ -#define STV_DEFAULT 0 /* Default symbol visibility rules */ -#define STV_INTERNAL 1 /* Processor specific hidden class */ -#define STV_HIDDEN 2 /* Sym unavailable in other modules */ -#define STV_PROTECTED 3 /* Not preemptible, not exported */ - - -/* Relocation table entry without addend (in section of type SHT_REL). */ - -typedef struct -{ - Elf32_Addr r_offset; /* Address */ - Elf32_Word r_info; /* Relocation type and symbol index */ -} Elf32_Rel; - -/* I have seen two different definitions of the Elf64_Rel and - Elf64_Rela structures, so we'll leave them out until Novell (or - whoever) gets their act together. */ -/* The following, at least, is used on Sparc v9, MIPS, and Alpha. */ - -typedef struct -{ - Elf64_Addr r_offset; /* Address */ - Elf64_Xword r_info; /* Relocation type and symbol index */ -} Elf64_Rel; - -/* Relocation table entry with addend (in section of type SHT_RELA). */ - -typedef struct -{ - Elf32_Addr r_offset; /* Address */ - Elf32_Word r_info; /* Relocation type and symbol index */ - Elf32_Sword r_addend; /* Addend */ -} Elf32_Rela; - -typedef struct -{ - Elf64_Addr r_offset; /* Address */ - Elf64_Xword r_info; /* Relocation type and symbol index */ - Elf64_Sxword r_addend; /* Addend */ -} Elf64_Rela; - -/* How to extract and insert information held in the r_info field. */ - -#define ELF32_R_SYM(val) ((val) >> 8) -#define ELF32_R_TYPE(val) ((val) & 0xff) -#define ELF32_R_INFO(sym, type) (((sym) << 8) + ((type) & 0xff)) - -#define ELF64_R_SYM(i) ((i) >> 32) -#define ELF64_R_TYPE(i) ((i) & 0xffffffff) -#define ELF64_R_INFO(sym,type) ((((Elf64_Xword) (sym)) << 32) + (type)) - -/* Program segment header. */ - -typedef struct -{ - Elf32_Word p_type; /* Segment type */ - Elf32_Off p_offset; /* Segment file offset */ - Elf32_Addr p_vaddr; /* Segment virtual address */ - Elf32_Addr p_paddr; /* Segment physical address */ - Elf32_Word p_filesz; /* Segment size in file */ - Elf32_Word p_memsz; /* Segment size in memory */ - Elf32_Word p_flags; /* Segment flags */ - Elf32_Word p_align; /* Segment alignment */ -} Elf32_Phdr; - -typedef struct -{ - Elf64_Word p_type; /* Segment type */ - Elf64_Word p_flags; /* Segment flags */ - Elf64_Off p_offset; /* Segment file offset */ - Elf64_Addr p_vaddr; /* Segment virtual address */ - Elf64_Addr p_paddr; /* Segment physical address */ - Elf64_Xword p_filesz; /* Segment size in file */ - Elf64_Xword p_memsz; /* Segment size in memory */ - Elf64_Xword p_align; /* Segment alignment */ -} Elf64_Phdr; - -/* Special value for e_phnum. This indicates that the real number of - program headers is too large to fit into e_phnum. Instead the real - value is in the field sh_info of section 0. */ - -#define PN_XNUM 0xffff - -/* Legal values for p_type (segment type). */ - -#define PT_NULL 0 /* Program header table entry unused */ -#define PT_LOAD 1 /* Loadable program segment */ -#define PT_DYNAMIC 2 /* Dynamic linking information */ -#define PT_INTERP 3 /* Program interpreter */ -#define PT_NOTE 4 /* Auxiliary information */ -#define PT_SHLIB 5 /* Reserved */ -#define PT_PHDR 6 /* Entry for header table itself */ -#define PT_TLS 7 /* Thread-local storage segment */ -#define PT_NUM 8 /* Number of defined types */ -#define PT_LOOS 0x60000000 /* Start of OS-specific */ -#define PT_GNU_EH_FRAME 0x6474e550 /* GCC .eh_frame_hdr segment */ -#define PT_GNU_STACK 0x6474e551 /* Indicates stack executability */ -#define PT_GNU_RELRO 0x6474e552 /* Read-only after relocation */ -#define PT_LOSUNW 0x6ffffffa -#define PT_SUNWBSS 0x6ffffffa /* Sun Specific segment */ -#define PT_SUNWSTACK 0x6ffffffb /* Stack segment */ -#define PT_HISUNW 0x6fffffff -#define PT_HIOS 0x6fffffff /* End of OS-specific */ -#define PT_LOPROC 0x70000000 /* Start of processor-specific */ -#define PT_HIPROC 0x7fffffff /* End of processor-specific */ - -/* Legal values for p_flags (segment flags). */ - -#define PF_X (1 << 0) /* Segment is executable */ -#define PF_W (1 << 1) /* Segment is writable */ -#define PF_R (1 << 2) /* Segment is readable */ -#define PF_MASKOS 0x0ff00000 /* OS-specific */ -#define PF_MASKPROC 0xf0000000 /* Processor-specific */ - -/* Legal values for note segment descriptor types for core files. */ - -#define NT_PRSTATUS 1 /* Contains copy of prstatus struct */ -#define NT_FPREGSET 2 /* Contains copy of fpregset struct */ -#define NT_PRPSINFO 3 /* Contains copy of prpsinfo struct */ -#define NT_PRXREG 4 /* Contains copy of prxregset struct */ -#define NT_TASKSTRUCT 4 /* Contains copy of task structure */ -#define NT_PLATFORM 5 /* String from sysinfo(SI_PLATFORM) */ -#define NT_AUXV 6 /* Contains copy of auxv array */ -#define NT_GWINDOWS 7 /* Contains copy of gwindows struct */ -#define NT_ASRS 8 /* Contains copy of asrset struct */ -#define NT_PSTATUS 10 /* Contains copy of pstatus struct */ -#define NT_PSINFO 13 /* Contains copy of psinfo struct */ -#define NT_PRCRED 14 /* Contains copy of prcred struct */ -#define NT_UTSNAME 15 /* Contains copy of utsname struct */ -#define NT_LWPSTATUS 16 /* Contains copy of lwpstatus struct */ -#define NT_LWPSINFO 17 /* Contains copy of lwpinfo struct */ -#define NT_PRFPXREG 20 /* Contains copy of fprxregset struct */ -#define NT_SIGINFO 0x53494749 /* Contains copy of siginfo_t, - size might increase */ -#define NT_FILE 0x46494c45 /* Contains information about mapped - files */ -#define NT_PRXFPREG 0x46e62b7f /* Contains copy of user_fxsr_struct */ -#define NT_PPC_VMX 0x100 /* PowerPC Altivec/VMX registers */ -#define NT_PPC_SPE 0x101 /* PowerPC SPE/EVR registers */ -#define NT_PPC_VSX 0x102 /* PowerPC VSX registers */ -#define NT_386_TLS 0x200 /* i386 TLS slots (struct user_desc) */ -#define NT_386_IOPERM 0x201 /* x86 io permission bitmap (1=deny) */ -#define NT_X86_XSTATE 0x202 /* x86 extended state using xsave */ -#define NT_S390_HIGH_GPRS 0x300 /* s390 upper register halves */ -#define NT_S390_TIMER 0x301 /* s390 timer register */ -#define NT_S390_TODCMP 0x302 /* s390 TOD clock comparator register */ -#define NT_S390_TODPREG 0x303 /* s390 TOD programmable register */ -#define NT_S390_CTRS 0x304 /* s390 control registers */ -#define NT_S390_PREFIX 0x305 /* s390 prefix register */ -#define NT_S390_LAST_BREAK 0x306 /* s390 breaking event address */ -#define NT_S390_SYSTEM_CALL 0x307 /* s390 system call restart data */ -#define NT_S390_TDB 0x308 /* s390 transaction diagnostic block */ -#define NT_ARM_VFP 0x400 /* ARM VFP/NEON registers */ -#define NT_ARM_TLS 0x401 /* ARM TLS register */ -#define NT_ARM_HW_BREAK 0x402 /* ARM hardware breakpoint registers */ -#define NT_ARM_HW_WATCH 0x403 /* ARM hardware watchpoint registers */ -#define NT_ARM_SYSTEM_CALL 0x404 /* ARM system call number */ - -/* Legal values for the note segment descriptor types for object files. */ - -#define NT_VERSION 1 /* Contains a version string. */ - - -/* Dynamic section entry. */ - -typedef struct -{ - Elf32_Sword d_tag; /* Dynamic entry type */ - union - { - Elf32_Word d_val; /* Integer value */ - Elf32_Addr d_ptr; /* Address value */ - } d_un; -} Elf32_Dyn; - -typedef struct -{ - Elf64_Sxword d_tag; /* Dynamic entry type */ - union - { - Elf64_Xword d_val; /* Integer value */ - Elf64_Addr d_ptr; /* Address value */ - } d_un; -} Elf64_Dyn; - -/* Legal values for d_tag (dynamic entry type). */ - -#define DT_NULL 0 /* Marks end of dynamic section */ -#define DT_NEEDED 1 /* Name of needed library */ -#define DT_PLTRELSZ 2 /* Size in bytes of PLT relocs */ -#define DT_PLTGOT 3 /* Processor defined value */ -#define DT_HASH 4 /* Address of symbol hash table */ -#define DT_STRTAB 5 /* Address of string table */ -#define DT_SYMTAB 6 /* Address of symbol table */ -#define DT_RELA 7 /* Address of Rela relocs */ -#define DT_RELASZ 8 /* Total size of Rela relocs */ -#define DT_RELAENT 9 /* Size of one Rela reloc */ -#define DT_STRSZ 10 /* Size of string table */ -#define DT_SYMENT 11 /* Size of one symbol table entry */ -#define DT_INIT 12 /* Address of init function */ -#define DT_FINI 13 /* Address of termination function */ -#define DT_SONAME 14 /* Name of shared object */ -#define DT_RPATH 15 /* Library search path (deprecated) */ -#define DT_SYMBOLIC 16 /* Start symbol search here */ -#define DT_REL 17 /* Address of Rel relocs */ -#define DT_RELSZ 18 /* Total size of Rel relocs */ -#define DT_RELENT 19 /* Size of one Rel reloc */ -#define DT_PLTREL 20 /* Type of reloc in PLT */ -#define DT_DEBUG 21 /* For debugging; unspecified */ -#define DT_TEXTREL 22 /* Reloc might modify .text */ -#define DT_JMPREL 23 /* Address of PLT relocs */ -#define DT_BIND_NOW 24 /* Process relocations of object */ -#define DT_INIT_ARRAY 25 /* Array with addresses of init fct */ -#define DT_FINI_ARRAY 26 /* Array with addresses of fini fct */ -#define DT_INIT_ARRAYSZ 27 /* Size in bytes of DT_INIT_ARRAY */ -#define DT_FINI_ARRAYSZ 28 /* Size in bytes of DT_FINI_ARRAY */ -#define DT_RUNPATH 29 /* Library search path */ -#define DT_FLAGS 30 /* Flags for the object being loaded */ -#define DT_ENCODING 32 /* Start of encoded range */ -#define DT_PREINIT_ARRAY 32 /* Array with addresses of preinit fct*/ -#define DT_PREINIT_ARRAYSZ 33 /* size in bytes of DT_PREINIT_ARRAY */ -#define DT_NUM 34 /* Number used */ -#define DT_LOOS 0x6000000d /* Start of OS-specific */ -#define DT_HIOS 0x6ffff000 /* End of OS-specific */ -#define DT_LOPROC 0x70000000 /* Start of processor-specific */ -#define DT_HIPROC 0x7fffffff /* End of processor-specific */ -#define DT_PROCNUM DT_MIPS_NUM /* Most used by any processor */ - -/* DT_* entries which fall between DT_VALRNGHI & DT_VALRNGLO use the - Dyn.d_un.d_val field of the Elf*_Dyn structure. This follows Sun's - approach. */ -#define DT_VALRNGLO 0x6ffffd00 -#define DT_GNU_PRELINKED 0x6ffffdf5 /* Prelinking timestamp */ -#define DT_GNU_CONFLICTSZ 0x6ffffdf6 /* Size of conflict section */ -#define DT_GNU_LIBLISTSZ 0x6ffffdf7 /* Size of library list */ -#define DT_CHECKSUM 0x6ffffdf8 -#define DT_PLTPADSZ 0x6ffffdf9 -#define DT_MOVEENT 0x6ffffdfa -#define DT_MOVESZ 0x6ffffdfb -#define DT_FEATURE_1 0x6ffffdfc /* Feature selection (DTF_*). */ -#define DT_POSFLAG_1 0x6ffffdfd /* Flags for DT_* entries, effecting - the following DT_* entry. */ -#define DT_SYMINSZ 0x6ffffdfe /* Size of syminfo table (in bytes) */ -#define DT_SYMINENT 0x6ffffdff /* Entry size of syminfo */ -#define DT_VALRNGHI 0x6ffffdff -#define DT_VALTAGIDX(tag) (DT_VALRNGHI - (tag)) /* Reverse order! */ -#define DT_VALNUM 12 - -/* DT_* entries which fall between DT_ADDRRNGHI & DT_ADDRRNGLO use the - Dyn.d_un.d_ptr field of the Elf*_Dyn structure. - - If any adjustment is made to the ELF object after it has been - built these entries will need to be adjusted. */ -#define DT_ADDRRNGLO 0x6ffffe00 -#define DT_GNU_HASH 0x6ffffef5 /* GNU-style hash table. */ -#define DT_TLSDESC_PLT 0x6ffffef6 -#define DT_TLSDESC_GOT 0x6ffffef7 -#define DT_GNU_CONFLICT 0x6ffffef8 /* Start of conflict section */ -#define DT_GNU_LIBLIST 0x6ffffef9 /* Library list */ -#define DT_CONFIG 0x6ffffefa /* Configuration information. */ -#define DT_DEPAUDIT 0x6ffffefb /* Dependency auditing. */ -#define DT_AUDIT 0x6ffffefc /* Object auditing. */ -#define DT_PLTPAD 0x6ffffefd /* PLT padding. */ -#define DT_MOVETAB 0x6ffffefe /* Move table. */ -#define DT_SYMINFO 0x6ffffeff /* Syminfo table. */ -#define DT_ADDRRNGHI 0x6ffffeff -#define DT_ADDRTAGIDX(tag) (DT_ADDRRNGHI - (tag)) /* Reverse order! */ -#define DT_ADDRNUM 11 - -/* The versioning entry types. The next are defined as part of the - GNU extension. */ -#define DT_VERSYM 0x6ffffff0 - -#define DT_RELACOUNT 0x6ffffff9 -#define DT_RELCOUNT 0x6ffffffa - -/* These were chosen by Sun. */ -#define DT_FLAGS_1 0x6ffffffb /* State flags, see DF_1_* below. */ -#define DT_VERDEF 0x6ffffffc /* Address of version definition - table */ -#define DT_VERDEFNUM 0x6ffffffd /* Number of version definitions */ -#define DT_VERNEED 0x6ffffffe /* Address of table with needed - versions */ -#define DT_VERNEEDNUM 0x6fffffff /* Number of needed versions */ -#define DT_VERSIONTAGIDX(tag) (DT_VERNEEDNUM - (tag)) /* Reverse order! */ -#define DT_VERSIONTAGNUM 16 - -/* Sun added these machine-independent extensions in the "processor-specific" - range. Be compatible. */ -#define DT_AUXILIARY 0x7ffffffd /* Shared object to load before self */ -#define DT_FILTER 0x7fffffff /* Shared object to get values from */ -#define DT_EXTRATAGIDX(tag) ((Elf32_Word)-((Elf32_Sword) (tag) <<1>>1)-1) -#define DT_EXTRANUM 3 - -/* Values of `d_un.d_val' in the DT_FLAGS entry. */ -#define DF_ORIGIN 0x00000001 /* Object may use DF_ORIGIN */ -#define DF_SYMBOLIC 0x00000002 /* Symbol resolutions starts here */ -#define DF_TEXTREL 0x00000004 /* Object contains text relocations */ -#define DF_BIND_NOW 0x00000008 /* No lazy binding for this object */ -#define DF_STATIC_TLS 0x00000010 /* Module uses the static TLS model */ - -/* State flags selectable in the `d_un.d_val' element of the DT_FLAGS_1 - entry in the dynamic section. */ -#define DF_1_NOW 0x00000001 /* Set RTLD_NOW for this object. */ -#define DF_1_GLOBAL 0x00000002 /* Set RTLD_GLOBAL for this object. */ -#define DF_1_GROUP 0x00000004 /* Set RTLD_GROUP for this object. */ -#define DF_1_NODELETE 0x00000008 /* Set RTLD_NODELETE for this object.*/ -#define DF_1_LOADFLTR 0x00000010 /* Trigger filtee loading at runtime.*/ -#define DF_1_INITFIRST 0x00000020 /* Set RTLD_INITFIRST for this object*/ -#define DF_1_NOOPEN 0x00000040 /* Set RTLD_NOOPEN for this object. */ -#define DF_1_ORIGIN 0x00000080 /* $ORIGIN must be handled. */ -#define DF_1_DIRECT 0x00000100 /* Direct binding enabled. */ -#define DF_1_TRANS 0x00000200 -#define DF_1_INTERPOSE 0x00000400 /* Object is used to interpose. */ -#define DF_1_NODEFLIB 0x00000800 /* Ignore default lib search path. */ -#define DF_1_NODUMP 0x00001000 /* Object can't be dldump'ed. */ -#define DF_1_CONFALT 0x00002000 /* Configuration alternative created.*/ -#define DF_1_ENDFILTEE 0x00004000 /* Filtee terminates filters search. */ -#define DF_1_DISPRELDNE 0x00008000 /* Disp reloc applied at build time. */ -#define DF_1_DISPRELPND 0x00010000 /* Disp reloc applied at run-time. */ -#define DF_1_NODIRECT 0x00020000 /* Object has no-direct binding. */ -#define DF_1_IGNMULDEF 0x00040000 -#define DF_1_NOKSYMS 0x00080000 -#define DF_1_NOHDR 0x00100000 -#define DF_1_EDITED 0x00200000 /* Object is modified after built. */ -#define DF_1_NORELOC 0x00400000 -#define DF_1_SYMINTPOSE 0x00800000 /* Object has individual interposers. */ -#define DF_1_GLOBAUDIT 0x01000000 /* Global auditing required. */ -#define DF_1_SINGLETON 0x02000000 /* Singleton symbols are used. */ - -/* Flags for the feature selection in DT_FEATURE_1. */ -#define DTF_1_PARINIT 0x00000001 -#define DTF_1_CONFEXP 0x00000002 - -/* Flags in the DT_POSFLAG_1 entry effecting only the next DT_* entry. */ -#define DF_P1_LAZYLOAD 0x00000001 /* Lazyload following object. */ -#define DF_P1_GROUPPERM 0x00000002 /* Symbols from next object are not - generally available. */ - -/* Version definition sections. */ - -typedef struct -{ - Elf32_Half vd_version; /* Version revision */ - Elf32_Half vd_flags; /* Version information */ - Elf32_Half vd_ndx; /* Version Index */ - Elf32_Half vd_cnt; /* Number of associated aux entries */ - Elf32_Word vd_hash; /* Version name hash value */ - Elf32_Word vd_aux; /* Offset in bytes to verdaux array */ - Elf32_Word vd_next; /* Offset in bytes to next verdef - entry */ -} Elf32_Verdef; - -typedef struct -{ - Elf64_Half vd_version; /* Version revision */ - Elf64_Half vd_flags; /* Version information */ - Elf64_Half vd_ndx; /* Version Index */ - Elf64_Half vd_cnt; /* Number of associated aux entries */ - Elf64_Word vd_hash; /* Version name hash value */ - Elf64_Word vd_aux; /* Offset in bytes to verdaux array */ - Elf64_Word vd_next; /* Offset in bytes to next verdef - entry */ -} Elf64_Verdef; - - -/* Legal values for vd_version (version revision). */ -#define VER_DEF_NONE 0 /* No version */ -#define VER_DEF_CURRENT 1 /* Current version */ -#define VER_DEF_NUM 2 /* Given version number */ - -/* Legal values for vd_flags (version information flags). */ -#define VER_FLG_BASE 0x1 /* Version definition of file itself */ -#define VER_FLG_WEAK 0x2 /* Weak version identifier */ - -/* Versym symbol index values. */ -#define VER_NDX_LOCAL 0 /* Symbol is local. */ -#define VER_NDX_GLOBAL 1 /* Symbol is global. */ -#define VER_NDX_LORESERVE 0xff00 /* Beginning of reserved entries. */ -#define VER_NDX_ELIMINATE 0xff01 /* Symbol is to be eliminated. */ - -/* Auxialiary version information. */ - -typedef struct -{ - Elf32_Word vda_name; /* Version or dependency names */ - Elf32_Word vda_next; /* Offset in bytes to next verdaux - entry */ -} Elf32_Verdaux; - -typedef struct -{ - Elf64_Word vda_name; /* Version or dependency names */ - Elf64_Word vda_next; /* Offset in bytes to next verdaux - entry */ -} Elf64_Verdaux; - - -/* Version dependency section. */ - -typedef struct -{ - Elf32_Half vn_version; /* Version of structure */ - Elf32_Half vn_cnt; /* Number of associated aux entries */ - Elf32_Word vn_file; /* Offset of filename for this - dependency */ - Elf32_Word vn_aux; /* Offset in bytes to vernaux array */ - Elf32_Word vn_next; /* Offset in bytes to next verneed - entry */ -} Elf32_Verneed; - -typedef struct -{ - Elf64_Half vn_version; /* Version of structure */ - Elf64_Half vn_cnt; /* Number of associated aux entries */ - Elf64_Word vn_file; /* Offset of filename for this - dependency */ - Elf64_Word vn_aux; /* Offset in bytes to vernaux array */ - Elf64_Word vn_next; /* Offset in bytes to next verneed - entry */ -} Elf64_Verneed; - - -/* Legal values for vn_version (version revision). */ -#define VER_NEED_NONE 0 /* No version */ -#define VER_NEED_CURRENT 1 /* Current version */ -#define VER_NEED_NUM 2 /* Given version number */ - -/* Auxiliary needed version information. */ - -typedef struct -{ - Elf32_Word vna_hash; /* Hash value of dependency name */ - Elf32_Half vna_flags; /* Dependency specific information */ - Elf32_Half vna_other; /* Unused */ - Elf32_Word vna_name; /* Dependency name string offset */ - Elf32_Word vna_next; /* Offset in bytes to next vernaux - entry */ -} Elf32_Vernaux; - -typedef struct -{ - Elf64_Word vna_hash; /* Hash value of dependency name */ - Elf64_Half vna_flags; /* Dependency specific information */ - Elf64_Half vna_other; /* Unused */ - Elf64_Word vna_name; /* Dependency name string offset */ - Elf64_Word vna_next; /* Offset in bytes to next vernaux - entry */ -} Elf64_Vernaux; - - -/* Legal values for vna_flags. */ -#define VER_FLG_WEAK 0x2 /* Weak version identifier */ - - -/* Auxiliary vector. */ - -/* This vector is normally only used by the program interpreter. The - usual definition in an ABI supplement uses the name auxv_t. The - vector is not usually defined in a standard <elf.h> file, but it - can't hurt. We rename it to avoid conflicts. The sizes of these - types are an arrangement between the exec server and the program - interpreter, so we don't fully specify them here. */ - -typedef struct -{ - uint32_t a_type; /* Entry type */ - union - { - uint32_t a_val; /* Integer value */ - /* We use to have pointer elements added here. We cannot do that, - though, since it does not work when using 32-bit definitions - on 64-bit platforms and vice versa. */ - } a_un; -} Elf32_auxv_t; - -typedef struct -{ - uint64_t a_type; /* Entry type */ - union - { - uint64_t a_val; /* Integer value */ - /* We use to have pointer elements added here. We cannot do that, - though, since it does not work when using 32-bit definitions - on 64-bit platforms and vice versa. */ - } a_un; -} Elf64_auxv_t; - -/* Legal values for a_type (entry type). */ - -#define AT_NULL 0 /* End of vector */ -#define AT_IGNORE 1 /* Entry should be ignored */ -#define AT_EXECFD 2 /* File descriptor of program */ -#define AT_PHDR 3 /* Program headers for program */ -#define AT_PHENT 4 /* Size of program header entry */ -#define AT_PHNUM 5 /* Number of program headers */ -#define AT_PAGESZ 6 /* System page size */ -#define AT_BASE 7 /* Base address of interpreter */ -#define AT_FLAGS 8 /* Flags */ -#define AT_ENTRY 9 /* Entry point of program */ -#define AT_NOTELF 10 /* Program is not ELF */ -#define AT_UID 11 /* Real uid */ -#define AT_EUID 12 /* Effective uid */ -#define AT_GID 13 /* Real gid */ -#define AT_EGID 14 /* Effective gid */ -#define AT_CLKTCK 17 /* Frequency of times() */ - -/* Some more special a_type values describing the hardware. */ -#define AT_PLATFORM 15 /* String identifying platform. */ -#define AT_HWCAP 16 /* Machine-dependent hints about - processor capabilities. */ - -/* This entry gives some information about the FPU initialization - performed by the kernel. */ -#define AT_FPUCW 18 /* Used FPU control word. */ - -/* Cache block sizes. */ -#define AT_DCACHEBSIZE 19 /* Data cache block size. */ -#define AT_ICACHEBSIZE 20 /* Instruction cache block size. */ -#define AT_UCACHEBSIZE 21 /* Unified cache block size. */ - -/* A special ignored value for PPC, used by the kernel to control the - interpretation of the AUXV. Must be > 16. */ -#define AT_IGNOREPPC 22 /* Entry should be ignored. */ - -#define AT_SECURE 23 /* Boolean, was exec setuid-like? */ - -#define AT_BASE_PLATFORM 24 /* String identifying real platforms.*/ - -#define AT_RANDOM 25 /* Address of 16 random bytes. */ - -#define AT_HWCAP2 26 /* More machine-dependent hints about - processor capabilities. */ - -#define AT_EXECFN 31 /* Filename of executable. */ - -/* Pointer to the global system page used for system calls and other - nice things. */ -#define AT_SYSINFO 32 -#define AT_SYSINFO_EHDR 33 - -/* Shapes of the caches. Bits 0-3 contains associativity; bits 4-7 contains - log2 of line size; mask those to get cache size. */ -#define AT_L1I_CACHESHAPE 34 -#define AT_L1D_CACHESHAPE 35 -#define AT_L2_CACHESHAPE 36 -#define AT_L3_CACHESHAPE 37 - -/* Shapes of the caches, with more room to describe them. - *GEOMETRY are comprised of cache line size in bytes in the bottom 16 bits - and the cache associativity in the next 16 bits. */ -#define AT_L1I_CACHESIZE 40 -#define AT_L1I_CACHEGEOMETRY 41 -#define AT_L1D_CACHESIZE 42 -#define AT_L1D_CACHEGEOMETRY 43 -#define AT_L2_CACHESIZE 44 -#define AT_L2_CACHEGEOMETRY 45 -#define AT_L3_CACHESIZE 46 -#define AT_L3_CACHEGEOMETRY 47 - -/* Note section contents. Each entry in the note section begins with - a header of a fixed form. */ - -typedef struct -{ - Elf32_Word n_namesz; /* Length of the note's name. */ - Elf32_Word n_descsz; /* Length of the note's descriptor. */ - Elf32_Word n_type; /* Type of the note. */ -} Elf32_Nhdr; - -typedef struct -{ - Elf64_Word n_namesz; /* Length of the note's name. */ - Elf64_Word n_descsz; /* Length of the note's descriptor. */ - Elf64_Word n_type; /* Type of the note. */ -} Elf64_Nhdr; - -/* Known names of notes. */ - -/* Solaris entries in the note section have this name. */ -#define ELF_NOTE_SOLARIS "SUNW Solaris" - -/* Note entries for GNU systems have this name. */ -#define ELF_NOTE_GNU "GNU" - - -/* Defined types of notes for Solaris. */ - -/* Value of descriptor (one word) is desired pagesize for the binary. */ -#define ELF_NOTE_PAGESIZE_HINT 1 - - -/* Defined note types for GNU systems. */ - -/* ABI information. The descriptor consists of words: - word 0: OS descriptor - word 1: major version of the ABI - word 2: minor version of the ABI - word 3: subminor version of the ABI -*/ -#define NT_GNU_ABI_TAG 1 -#define ELF_NOTE_ABI NT_GNU_ABI_TAG /* Old name. */ - -/* Known OSes. These values can appear in word 0 of an - NT_GNU_ABI_TAG note section entry. */ -#define ELF_NOTE_OS_LINUX 0 -#define ELF_NOTE_OS_GNU 1 -#define ELF_NOTE_OS_SOLARIS2 2 -#define ELF_NOTE_OS_FREEBSD 3 - -/* Synthetic hwcap information. The descriptor begins with two words: - word 0: number of entries - word 1: bitmask of enabled entries - Then follow variable-length entries, one byte followed by a - '\0'-terminated hwcap name string. The byte gives the bit - number to test if enabled, (1U << bit) & bitmask. */ -#define NT_GNU_HWCAP 2 - -/* Build ID bits as generated by ld --build-id. - The descriptor consists of any nonzero number of bytes. */ -#define NT_GNU_BUILD_ID 3 - -/* Version note generated by GNU gold containing a version string. */ -#define NT_GNU_GOLD_VERSION 4 - - -/* Move records. */ -typedef struct -{ - Elf32_Xword m_value; /* Symbol value. */ - Elf32_Word m_info; /* Size and index. */ - Elf32_Word m_poffset; /* Symbol offset. */ - Elf32_Half m_repeat; /* Repeat count. */ - Elf32_Half m_stride; /* Stride info. */ -} Elf32_Move; - -typedef struct -{ - Elf64_Xword m_value; /* Symbol value. */ - Elf64_Xword m_info; /* Size and index. */ - Elf64_Xword m_poffset; /* Symbol offset. */ - Elf64_Half m_repeat; /* Repeat count. */ - Elf64_Half m_stride; /* Stride info. */ -} Elf64_Move; - -/* Macro to construct move records. */ -#define ELF32_M_SYM(info) ((info) >> 8) -#define ELF32_M_SIZE(info) ((unsigned char) (info)) -#define ELF32_M_INFO(sym, size) (((sym) << 8) + (unsigned char) (size)) - -#define ELF64_M_SYM(info) ELF32_M_SYM (info) -#define ELF64_M_SIZE(info) ELF32_M_SIZE (info) -#define ELF64_M_INFO(sym, size) ELF32_M_INFO (sym, size) - - -/* Motorola 68k specific definitions. */ - -/* Values for Elf32_Ehdr.e_flags. */ -#define EF_CPU32 0x00810000 - -/* m68k relocs. */ - -#define R_68K_NONE 0 /* No reloc */ -#define R_68K_32 1 /* Direct 32 bit */ -#define R_68K_16 2 /* Direct 16 bit */ -#define R_68K_8 3 /* Direct 8 bit */ -#define R_68K_PC32 4 /* PC relative 32 bit */ -#define R_68K_PC16 5 /* PC relative 16 bit */ -#define R_68K_PC8 6 /* PC relative 8 bit */ -#define R_68K_GOT32 7 /* 32 bit PC relative GOT entry */ -#define R_68K_GOT16 8 /* 16 bit PC relative GOT entry */ -#define R_68K_GOT8 9 /* 8 bit PC relative GOT entry */ -#define R_68K_GOT32O 10 /* 32 bit GOT offset */ -#define R_68K_GOT16O 11 /* 16 bit GOT offset */ -#define R_68K_GOT8O 12 /* 8 bit GOT offset */ -#define R_68K_PLT32 13 /* 32 bit PC relative PLT address */ -#define R_68K_PLT16 14 /* 16 bit PC relative PLT address */ -#define R_68K_PLT8 15 /* 8 bit PC relative PLT address */ -#define R_68K_PLT32O 16 /* 32 bit PLT offset */ -#define R_68K_PLT16O 17 /* 16 bit PLT offset */ -#define R_68K_PLT8O 18 /* 8 bit PLT offset */ -#define R_68K_COPY 19 /* Copy symbol at runtime */ -#define R_68K_GLOB_DAT 20 /* Create GOT entry */ -#define R_68K_JMP_SLOT 21 /* Create PLT entry */ -#define R_68K_RELATIVE 22 /* Adjust by program base */ -#define R_68K_TLS_GD32 25 /* 32 bit GOT offset for GD */ -#define R_68K_TLS_GD16 26 /* 16 bit GOT offset for GD */ -#define R_68K_TLS_GD8 27 /* 8 bit GOT offset for GD */ -#define R_68K_TLS_LDM32 28 /* 32 bit GOT offset for LDM */ -#define R_68K_TLS_LDM16 29 /* 16 bit GOT offset for LDM */ -#define R_68K_TLS_LDM8 30 /* 8 bit GOT offset for LDM */ -#define R_68K_TLS_LDO32 31 /* 32 bit module-relative offset */ -#define R_68K_TLS_LDO16 32 /* 16 bit module-relative offset */ -#define R_68K_TLS_LDO8 33 /* 8 bit module-relative offset */ -#define R_68K_TLS_IE32 34 /* 32 bit GOT offset for IE */ -#define R_68K_TLS_IE16 35 /* 16 bit GOT offset for IE */ -#define R_68K_TLS_IE8 36 /* 8 bit GOT offset for IE */ -#define R_68K_TLS_LE32 37 /* 32 bit offset relative to - static TLS block */ -#define R_68K_TLS_LE16 38 /* 16 bit offset relative to - static TLS block */ -#define R_68K_TLS_LE8 39 /* 8 bit offset relative to - static TLS block */ -#define R_68K_TLS_DTPMOD32 40 /* 32 bit module number */ -#define R_68K_TLS_DTPREL32 41 /* 32 bit module-relative offset */ -#define R_68K_TLS_TPREL32 42 /* 32 bit TP-relative offset */ -/* Keep this the last entry. */ -#define R_68K_NUM 43 - -/* Intel 80386 specific definitions. */ - -/* i386 relocs. */ - -#define R_386_NONE 0 /* No reloc */ -#define R_386_32 1 /* Direct 32 bit */ -#define R_386_PC32 2 /* PC relative 32 bit */ -#define R_386_GOT32 3 /* 32 bit GOT entry */ -#define R_386_PLT32 4 /* 32 bit PLT address */ -#define R_386_COPY 5 /* Copy symbol at runtime */ -#define R_386_GLOB_DAT 6 /* Create GOT entry */ -#define R_386_JMP_SLOT 7 /* Create PLT entry */ -#define R_386_RELATIVE 8 /* Adjust by program base */ -#define R_386_GOTOFF 9 /* 32 bit offset to GOT */ -#define R_386_GOTPC 10 /* 32 bit PC relative offset to GOT */ -#define R_386_32PLT 11 -#define R_386_TLS_TPOFF 14 /* Offset in static TLS block */ -#define R_386_TLS_IE 15 /* Address of GOT entry for static TLS - block offset */ -#define R_386_TLS_GOTIE 16 /* GOT entry for static TLS block - offset */ -#define R_386_TLS_LE 17 /* Offset relative to static TLS - block */ -#define R_386_TLS_GD 18 /* Direct 32 bit for GNU version of - general dynamic thread local data */ -#define R_386_TLS_LDM 19 /* Direct 32 bit for GNU version of - local dynamic thread local data - in LE code */ -#define R_386_16 20 -#define R_386_PC16 21 -#define R_386_8 22 -#define R_386_PC8 23 -#define R_386_TLS_GD_32 24 /* Direct 32 bit for general dynamic - thread local data */ -#define R_386_TLS_GD_PUSH 25 /* Tag for pushl in GD TLS code */ -#define R_386_TLS_GD_CALL 26 /* Relocation for call to - __tls_get_addr() */ -#define R_386_TLS_GD_POP 27 /* Tag for popl in GD TLS code */ -#define R_386_TLS_LDM_32 28 /* Direct 32 bit for local dynamic - thread local data in LE code */ -#define R_386_TLS_LDM_PUSH 29 /* Tag for pushl in LDM TLS code */ -#define R_386_TLS_LDM_CALL 30 /* Relocation for call to - __tls_get_addr() in LDM code */ -#define R_386_TLS_LDM_POP 31 /* Tag for popl in LDM TLS code */ -#define R_386_TLS_LDO_32 32 /* Offset relative to TLS block */ -#define R_386_TLS_IE_32 33 /* GOT entry for negated static TLS - block offset */ -#define R_386_TLS_LE_32 34 /* Negated offset relative to static - TLS block */ -#define R_386_TLS_DTPMOD32 35 /* ID of module containing symbol */ -#define R_386_TLS_DTPOFF32 36 /* Offset in TLS block */ -#define R_386_TLS_TPOFF32 37 /* Negated offset in static TLS block */ -#define R_386_SIZE32 38 /* 32-bit symbol size */ -#define R_386_TLS_GOTDESC 39 /* GOT offset for TLS descriptor. */ -#define R_386_TLS_DESC_CALL 40 /* Marker of call through TLS - descriptor for - relaxation. */ -#define R_386_TLS_DESC 41 /* TLS descriptor containing - pointer to code and to - argument, returning the TLS - offset for the symbol. */ -#define R_386_IRELATIVE 42 /* Adjust indirectly by program base */ -#define R_386_GOT32X 43 /* Load from 32 bit GOT entry, - relaxable. */ -/* Keep this the last entry. */ -#define R_386_NUM 44 - -/* SUN SPARC specific definitions. */ - -/* Legal values for ST_TYPE subfield of st_info (symbol type). */ - -#define STT_SPARC_REGISTER 13 /* Global register reserved to app. */ - -/* Values for Elf64_Ehdr.e_flags. */ - -#define EF_SPARCV9_MM 3 -#define EF_SPARCV9_TSO 0 -#define EF_SPARCV9_PSO 1 -#define EF_SPARCV9_RMO 2 -#define EF_SPARC_LEDATA 0x800000 /* little endian data */ -#define EF_SPARC_EXT_MASK 0xFFFF00 -#define EF_SPARC_32PLUS 0x000100 /* generic V8+ features */ -#define EF_SPARC_SUN_US1 0x000200 /* Sun UltraSPARC1 extensions */ -#define EF_SPARC_HAL_R1 0x000400 /* HAL R1 extensions */ -#define EF_SPARC_SUN_US3 0x000800 /* Sun UltraSPARCIII extensions */ - -/* SPARC relocs. */ - -#define R_SPARC_NONE 0 /* No reloc */ -#define R_SPARC_8 1 /* Direct 8 bit */ -#define R_SPARC_16 2 /* Direct 16 bit */ -#define R_SPARC_32 3 /* Direct 32 bit */ -#define R_SPARC_DISP8 4 /* PC relative 8 bit */ -#define R_SPARC_DISP16 5 /* PC relative 16 bit */ -#define R_SPARC_DISP32 6 /* PC relative 32 bit */ -#define R_SPARC_WDISP30 7 /* PC relative 30 bit shifted */ -#define R_SPARC_WDISP22 8 /* PC relative 22 bit shifted */ -#define R_SPARC_HI22 9 /* High 22 bit */ -#define R_SPARC_22 10 /* Direct 22 bit */ -#define R_SPARC_13 11 /* Direct 13 bit */ -#define R_SPARC_LO10 12 /* Truncated 10 bit */ -#define R_SPARC_GOT10 13 /* Truncated 10 bit GOT entry */ -#define R_SPARC_GOT13 14 /* 13 bit GOT entry */ -#define R_SPARC_GOT22 15 /* 22 bit GOT entry shifted */ -#define R_SPARC_PC10 16 /* PC relative 10 bit truncated */ -#define R_SPARC_PC22 17 /* PC relative 22 bit shifted */ -#define R_SPARC_WPLT30 18 /* 30 bit PC relative PLT address */ -#define R_SPARC_COPY 19 /* Copy symbol at runtime */ -#define R_SPARC_GLOB_DAT 20 /* Create GOT entry */ -#define R_SPARC_JMP_SLOT 21 /* Create PLT entry */ -#define R_SPARC_RELATIVE 22 /* Adjust by program base */ -#define R_SPARC_UA32 23 /* Direct 32 bit unaligned */ - -/* Additional Sparc64 relocs. */ - -#define R_SPARC_PLT32 24 /* Direct 32 bit ref to PLT entry */ -#define R_SPARC_HIPLT22 25 /* High 22 bit PLT entry */ -#define R_SPARC_LOPLT10 26 /* Truncated 10 bit PLT entry */ -#define R_SPARC_PCPLT32 27 /* PC rel 32 bit ref to PLT entry */ -#define R_SPARC_PCPLT22 28 /* PC rel high 22 bit PLT entry */ -#define R_SPARC_PCPLT10 29 /* PC rel trunc 10 bit PLT entry */ -#define R_SPARC_10 30 /* Direct 10 bit */ -#define R_SPARC_11 31 /* Direct 11 bit */ -#define R_SPARC_64 32 /* Direct 64 bit */ -#define R_SPARC_OLO10 33 /* 10bit with secondary 13bit addend */ -#define R_SPARC_HH22 34 /* Top 22 bits of direct 64 bit */ -#define R_SPARC_HM10 35 /* High middle 10 bits of ... */ -#define R_SPARC_LM22 36 /* Low middle 22 bits of ... */ -#define R_SPARC_PC_HH22 37 /* Top 22 bits of pc rel 64 bit */ -#define R_SPARC_PC_HM10 38 /* High middle 10 bit of ... */ -#define R_SPARC_PC_LM22 39 /* Low miggle 22 bits of ... */ -#define R_SPARC_WDISP16 40 /* PC relative 16 bit shifted */ -#define R_SPARC_WDISP19 41 /* PC relative 19 bit shifted */ -#define R_SPARC_GLOB_JMP 42 /* was part of v9 ABI but was removed */ -#define R_SPARC_7 43 /* Direct 7 bit */ -#define R_SPARC_5 44 /* Direct 5 bit */ -#define R_SPARC_6 45 /* Direct 6 bit */ -#define R_SPARC_DISP64 46 /* PC relative 64 bit */ -#define R_SPARC_PLT64 47 /* Direct 64 bit ref to PLT entry */ -#define R_SPARC_HIX22 48 /* High 22 bit complemented */ -#define R_SPARC_LOX10 49 /* Truncated 11 bit complemented */ -#define R_SPARC_H44 50 /* Direct high 12 of 44 bit */ -#define R_SPARC_M44 51 /* Direct mid 22 of 44 bit */ -#define R_SPARC_L44 52 /* Direct low 10 of 44 bit */ -#define R_SPARC_REGISTER 53 /* Global register usage */ -#define R_SPARC_UA64 54 /* Direct 64 bit unaligned */ -#define R_SPARC_UA16 55 /* Direct 16 bit unaligned */ -#define R_SPARC_TLS_GD_HI22 56 -#define R_SPARC_TLS_GD_LO10 57 -#define R_SPARC_TLS_GD_ADD 58 -#define R_SPARC_TLS_GD_CALL 59 -#define R_SPARC_TLS_LDM_HI22 60 -#define R_SPARC_TLS_LDM_LO10 61 -#define R_SPARC_TLS_LDM_ADD 62 -#define R_SPARC_TLS_LDM_CALL 63 -#define R_SPARC_TLS_LDO_HIX22 64 -#define R_SPARC_TLS_LDO_LOX10 65 -#define R_SPARC_TLS_LDO_ADD 66 -#define R_SPARC_TLS_IE_HI22 67 -#define R_SPARC_TLS_IE_LO10 68 -#define R_SPARC_TLS_IE_LD 69 -#define R_SPARC_TLS_IE_LDX 70 -#define R_SPARC_TLS_IE_ADD 71 -#define R_SPARC_TLS_LE_HIX22 72 -#define R_SPARC_TLS_LE_LOX10 73 -#define R_SPARC_TLS_DTPMOD32 74 -#define R_SPARC_TLS_DTPMOD64 75 -#define R_SPARC_TLS_DTPOFF32 76 -#define R_SPARC_TLS_DTPOFF64 77 -#define R_SPARC_TLS_TPOFF32 78 -#define R_SPARC_TLS_TPOFF64 79 -#define R_SPARC_GOTDATA_HIX22 80 -#define R_SPARC_GOTDATA_LOX10 81 -#define R_SPARC_GOTDATA_OP_HIX22 82 -#define R_SPARC_GOTDATA_OP_LOX10 83 -#define R_SPARC_GOTDATA_OP 84 -#define R_SPARC_H34 85 -#define R_SPARC_SIZE32 86 -#define R_SPARC_SIZE64 87 -#define R_SPARC_WDISP10 88 -#define R_SPARC_JMP_IREL 248 -#define R_SPARC_IRELATIVE 249 -#define R_SPARC_GNU_VTINHERIT 250 -#define R_SPARC_GNU_VTENTRY 251 -#define R_SPARC_REV32 252 -/* Keep this the last entry. */ -#define R_SPARC_NUM 253 - -/* For Sparc64, legal values for d_tag of Elf64_Dyn. */ - -#define DT_SPARC_REGISTER 0x70000001 -#define DT_SPARC_NUM 2 - -/* MIPS R3000 specific definitions. */ - -/* Legal values for e_flags field of Elf32_Ehdr. */ - -#define EF_MIPS_NOREORDER 1 /* A .noreorder directive was used. */ -#define EF_MIPS_PIC 2 /* Contains PIC code. */ -#define EF_MIPS_CPIC 4 /* Uses PIC calling sequence. */ -#define EF_MIPS_XGOT 8 -#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. */ - -/* Legal values for MIPS architecture level. */ - -#define EF_MIPS_ARCH_1 0x00000000 /* -mips1 code. */ -#define EF_MIPS_ARCH_2 0x10000000 /* -mips2 code. */ -#define EF_MIPS_ARCH_3 0x20000000 /* -mips3 code. */ -#define EF_MIPS_ARCH_4 0x30000000 /* -mips4 code. */ -#define EF_MIPS_ARCH_5 0x40000000 /* -mips5 code. */ -#define EF_MIPS_ARCH_32 0x50000000 /* MIPS32 code. */ -#define EF_MIPS_ARCH_64 0x60000000 /* MIPS64 code. */ -#define EF_MIPS_ARCH_32R2 0x70000000 /* MIPS32r2 code. */ -#define EF_MIPS_ARCH_64R2 0x80000000 /* MIPS64r2 code. */ - -/* The following are unofficial names and should not be used. */ - -#define E_MIPS_ARCH_1 EF_MIPS_ARCH_1 -#define E_MIPS_ARCH_2 EF_MIPS_ARCH_2 -#define E_MIPS_ARCH_3 EF_MIPS_ARCH_3 -#define E_MIPS_ARCH_4 EF_MIPS_ARCH_4 -#define E_MIPS_ARCH_5 EF_MIPS_ARCH_5 -#define E_MIPS_ARCH_32 EF_MIPS_ARCH_32 -#define E_MIPS_ARCH_64 EF_MIPS_ARCH_64 - -/* Special section indices. */ - -#define SHN_MIPS_ACOMMON 0xff00 /* Allocated common symbols. */ -#define SHN_MIPS_TEXT 0xff01 /* Allocated test symbols. */ -#define SHN_MIPS_DATA 0xff02 /* Allocated data symbols. */ -#define SHN_MIPS_SCOMMON 0xff03 /* Small common symbols. */ -#define SHN_MIPS_SUNDEFINED 0xff04 /* Small undefined symbols. */ - -/* Legal values for sh_type field of Elf32_Shdr. */ - -#define SHT_MIPS_LIBLIST 0x70000000 /* Shared objects used in link. */ -#define SHT_MIPS_MSYM 0x70000001 -#define SHT_MIPS_CONFLICT 0x70000002 /* Conflicting symbols. */ -#define SHT_MIPS_GPTAB 0x70000003 /* Global data area sizes. */ -#define SHT_MIPS_UCODE 0x70000004 /* Reserved for SGI/MIPS compilers */ -#define SHT_MIPS_DEBUG 0x70000005 /* MIPS ECOFF debugging info. */ -#define SHT_MIPS_REGINFO 0x70000006 /* Register usage information. */ -#define SHT_MIPS_PACKAGE 0x70000007 -#define SHT_MIPS_PACKSYM 0x70000008 -#define SHT_MIPS_RELD 0x70000009 -#define SHT_MIPS_IFACE 0x7000000b -#define SHT_MIPS_CONTENT 0x7000000c -#define SHT_MIPS_OPTIONS 0x7000000d /* Miscellaneous options. */ -#define SHT_MIPS_SHDR 0x70000010 -#define SHT_MIPS_FDESC 0x70000011 -#define SHT_MIPS_EXTSYM 0x70000012 -#define SHT_MIPS_DENSE 0x70000013 -#define SHT_MIPS_PDESC 0x70000014 -#define SHT_MIPS_LOCSYM 0x70000015 -#define SHT_MIPS_AUXSYM 0x70000016 -#define SHT_MIPS_OPTSYM 0x70000017 -#define SHT_MIPS_LOCSTR 0x70000018 -#define SHT_MIPS_LINE 0x70000019 -#define SHT_MIPS_RFDESC 0x7000001a -#define SHT_MIPS_DELTASYM 0x7000001b -#define SHT_MIPS_DELTAINST 0x7000001c -#define SHT_MIPS_DELTACLASS 0x7000001d -#define SHT_MIPS_DWARF 0x7000001e /* DWARF debugging information. */ -#define SHT_MIPS_DELTADECL 0x7000001f -#define SHT_MIPS_SYMBOL_LIB 0x70000020 -#define SHT_MIPS_EVENTS 0x70000021 /* Event section. */ -#define SHT_MIPS_TRANSLATE 0x70000022 -#define SHT_MIPS_PIXIE 0x70000023 -#define SHT_MIPS_XLATE 0x70000024 -#define SHT_MIPS_XLATE_DEBUG 0x70000025 -#define SHT_MIPS_WHIRL 0x70000026 -#define SHT_MIPS_EH_REGION 0x70000027 -#define SHT_MIPS_XLATE_OLD 0x70000028 -#define SHT_MIPS_PDR_EXCEPTION 0x70000029 - -/* Legal values for sh_flags field of Elf32_Shdr. */ - -#define SHF_MIPS_GPREL 0x10000000 /* Must be in global data area. */ -#define SHF_MIPS_MERGE 0x20000000 -#define SHF_MIPS_ADDR 0x40000000 -#define SHF_MIPS_STRINGS 0x80000000 -#define SHF_MIPS_NOSTRIP 0x08000000 -#define SHF_MIPS_LOCAL 0x04000000 -#define SHF_MIPS_NAMES 0x02000000 -#define SHF_MIPS_NODUPE 0x01000000 - - -/* Symbol tables. */ - -/* MIPS specific values for `st_other'. */ -#define STO_MIPS_DEFAULT 0x0 -#define STO_MIPS_INTERNAL 0x1 -#define STO_MIPS_HIDDEN 0x2 -#define STO_MIPS_PROTECTED 0x3 -#define STO_MIPS_PLT 0x8 -#define STO_MIPS_SC_ALIGN_UNUSED 0xff - -/* MIPS specific values for `st_info'. */ -#define STB_MIPS_SPLIT_COMMON 13 - -/* Entries found in sections of type SHT_MIPS_GPTAB. */ - -typedef union -{ - struct - { - Elf32_Word gt_current_g_value; /* -G value used for compilation. */ - Elf32_Word gt_unused; /* Not used. */ - } gt_header; /* First entry in section. */ - struct - { - Elf32_Word gt_g_value; /* If this value were used for -G. */ - Elf32_Word gt_bytes; /* This many bytes would be used. */ - } gt_entry; /* Subsequent entries in section. */ -} Elf32_gptab; - -/* Entry found in sections of type SHT_MIPS_REGINFO. */ - -typedef struct -{ - Elf32_Word ri_gprmask; /* General registers used. */ - Elf32_Word ri_cprmask[4]; /* Coprocessor registers used. */ - Elf32_Sword ri_gp_value; /* $gp register value. */ -} Elf32_RegInfo; - -/* Entries found in sections of type SHT_MIPS_OPTIONS. */ - -typedef struct -{ - unsigned char kind; /* Determines interpretation of the - variable part of descriptor. */ - unsigned char size; /* Size of descriptor, including header. */ - Elf32_Section section; /* Section header index of section affected, - 0 for global options. */ - Elf32_Word info; /* Kind-specific information. */ -} Elf_Options; - -/* Values for `kind' field in Elf_Options. */ - -#define ODK_NULL 0 /* Undefined. */ -#define ODK_REGINFO 1 /* Register usage information. */ -#define ODK_EXCEPTIONS 2 /* Exception processing options. */ -#define ODK_PAD 3 /* Section padding options. */ -#define ODK_HWPATCH 4 /* Hardware workarounds performed */ -#define ODK_FILL 5 /* record the fill value used by the linker. */ -#define ODK_TAGS 6 /* reserve space for desktop tools to write. */ -#define ODK_HWAND 7 /* HW workarounds. 'AND' bits when merging. */ -#define ODK_HWOR 8 /* HW workarounds. 'OR' bits when merging. */ - -/* Values for `info' in Elf_Options for ODK_EXCEPTIONS entries. */ - -#define OEX_FPU_MIN 0x1f /* FPE's which MUST be enabled. */ -#define OEX_FPU_MAX 0x1f00 /* FPE's which MAY be enabled. */ -#define OEX_PAGE0 0x10000 /* page zero must be mapped. */ -#define OEX_SMM 0x20000 /* Force sequential memory mode? */ -#define OEX_FPDBUG 0x40000 /* Force floating point debug mode? */ -#define OEX_PRECISEFP OEX_FPDBUG -#define OEX_DISMISS 0x80000 /* Dismiss invalid address faults? */ - -#define OEX_FPU_INVAL 0x10 -#define OEX_FPU_DIV0 0x08 -#define OEX_FPU_OFLO 0x04 -#define OEX_FPU_UFLO 0x02 -#define OEX_FPU_INEX 0x01 - -/* Masks for `info' in Elf_Options for an ODK_HWPATCH entry. */ - -#define OHW_R4KEOP 0x1 /* R4000 end-of-page patch. */ -#define OHW_R8KPFETCH 0x2 /* may need R8000 prefetch patch. */ -#define OHW_R5KEOP 0x4 /* R5000 end-of-page patch. */ -#define OHW_R5KCVTL 0x8 /* R5000 cvt.[ds].l bug. clean=1. */ - -#define OPAD_PREFIX 0x1 -#define OPAD_POSTFIX 0x2 -#define OPAD_SYMBOL 0x4 - -/* Entry found in `.options' section. */ - -typedef struct -{ - Elf32_Word hwp_flags1; /* Extra flags. */ - Elf32_Word hwp_flags2; /* Extra flags. */ -} Elf_Options_Hw; - -/* Masks for `info' in ElfOptions for ODK_HWAND and ODK_HWOR entries. */ - -#define OHWA0_R4KEOP_CHECKED 0x00000001 -#define OHWA1_R4KEOP_CLEAN 0x00000002 - -/* MIPS relocs. */ - -#define R_MIPS_NONE 0 /* No reloc */ -#define R_MIPS_16 1 /* Direct 16 bit */ -#define R_MIPS_32 2 /* Direct 32 bit */ -#define R_MIPS_REL32 3 /* PC relative 32 bit */ -#define R_MIPS_26 4 /* Direct 26 bit shifted */ -#define R_MIPS_HI16 5 /* High 16 bit */ -#define R_MIPS_LO16 6 /* Low 16 bit */ -#define R_MIPS_GPREL16 7 /* GP relative 16 bit */ -#define R_MIPS_LITERAL 8 /* 16 bit literal entry */ -#define R_MIPS_GOT16 9 /* 16 bit GOT entry */ -#define R_MIPS_PC16 10 /* PC relative 16 bit */ -#define R_MIPS_CALL16 11 /* 16 bit GOT entry for function */ -#define R_MIPS_GPREL32 12 /* GP relative 32 bit */ - -#define R_MIPS_SHIFT5 16 -#define R_MIPS_SHIFT6 17 -#define R_MIPS_64 18 -#define R_MIPS_GOT_DISP 19 -#define R_MIPS_GOT_PAGE 20 -#define R_MIPS_GOT_OFST 21 -#define R_MIPS_GOT_HI16 22 -#define R_MIPS_GOT_LO16 23 -#define R_MIPS_SUB 24 -#define R_MIPS_INSERT_A 25 -#define R_MIPS_INSERT_B 26 -#define R_MIPS_DELETE 27 -#define R_MIPS_HIGHER 28 -#define R_MIPS_HIGHEST 29 -#define R_MIPS_CALL_HI16 30 -#define R_MIPS_CALL_LO16 31 -#define R_MIPS_SCN_DISP 32 -#define R_MIPS_REL16 33 -#define R_MIPS_ADD_IMMEDIATE 34 -#define R_MIPS_PJUMP 35 -#define R_MIPS_RELGOT 36 -#define R_MIPS_JALR 37 -#define R_MIPS_TLS_DTPMOD32 38 /* Module number 32 bit */ -#define R_MIPS_TLS_DTPREL32 39 /* Module-relative offset 32 bit */ -#define R_MIPS_TLS_DTPMOD64 40 /* Module number 64 bit */ -#define R_MIPS_TLS_DTPREL64 41 /* Module-relative offset 64 bit */ -#define R_MIPS_TLS_GD 42 /* 16 bit GOT offset for GD */ -#define R_MIPS_TLS_LDM 43 /* 16 bit GOT offset for LDM */ -#define R_MIPS_TLS_DTPREL_HI16 44 /* Module-relative offset, high 16 bits */ -#define R_MIPS_TLS_DTPREL_LO16 45 /* Module-relative offset, low 16 bits */ -#define R_MIPS_TLS_GOTTPREL 46 /* 16 bit GOT offset for IE */ -#define R_MIPS_TLS_TPREL32 47 /* TP-relative offset, 32 bit */ -#define R_MIPS_TLS_TPREL64 48 /* TP-relative offset, 64 bit */ -#define R_MIPS_TLS_TPREL_HI16 49 /* TP-relative offset, high 16 bits */ -#define R_MIPS_TLS_TPREL_LO16 50 /* TP-relative offset, low 16 bits */ -#define R_MIPS_GLOB_DAT 51 -#define R_MIPS_COPY 126 -#define R_MIPS_JUMP_SLOT 127 -/* Keep this the last entry. */ -#define R_MIPS_NUM 128 - -/* 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_ABIFLAGS 0x70000003 /* FP mode requirement. */ - -/* Special program header types. */ - -#define PF_MIPS_LOCAL 0x10000000 - -/* Legal values for d_tag field of Elf32_Dyn. */ - -#define DT_MIPS_RLD_VERSION 0x70000001 /* Runtime linker interface version */ -#define DT_MIPS_TIME_STAMP 0x70000002 /* Timestamp */ -#define DT_MIPS_ICHECKSUM 0x70000003 /* Checksum */ -#define DT_MIPS_IVERSION 0x70000004 /* Version string (string tbl index) */ -#define DT_MIPS_FLAGS 0x70000005 /* Flags */ -#define DT_MIPS_BASE_ADDRESS 0x70000006 /* Base address */ -#define DT_MIPS_MSYM 0x70000007 -#define DT_MIPS_CONFLICT 0x70000008 /* Address of CONFLICT section */ -#define DT_MIPS_LIBLIST 0x70000009 /* Address of LIBLIST section */ -#define DT_MIPS_LOCAL_GOTNO 0x7000000a /* Number of local GOT entries */ -#define DT_MIPS_CONFLICTNO 0x7000000b /* Number of CONFLICT entries */ -#define DT_MIPS_LIBLISTNO 0x70000010 /* Number of LIBLIST entries */ -#define DT_MIPS_SYMTABNO 0x70000011 /* Number of DYNSYM entries */ -#define DT_MIPS_UNREFEXTNO 0x70000012 /* First external DYNSYM */ -#define DT_MIPS_GOTSYM 0x70000013 /* First GOT entry in DYNSYM */ -#define DT_MIPS_HIPAGENO 0x70000014 /* Number of GOT page table entries */ -#define DT_MIPS_RLD_MAP 0x70000016 /* Address of run time loader map. */ -#define DT_MIPS_DELTA_CLASS 0x70000017 /* Delta C++ class definition. */ -#define DT_MIPS_DELTA_CLASS_NO 0x70000018 /* Number of entries in - DT_MIPS_DELTA_CLASS. */ -#define DT_MIPS_DELTA_INSTANCE 0x70000019 /* Delta C++ class instances. */ -#define DT_MIPS_DELTA_INSTANCE_NO 0x7000001a /* Number of entries in - DT_MIPS_DELTA_INSTANCE. */ -#define DT_MIPS_DELTA_RELOC 0x7000001b /* Delta relocations. */ -#define DT_MIPS_DELTA_RELOC_NO 0x7000001c /* Number of entries in - DT_MIPS_DELTA_RELOC. */ -#define DT_MIPS_DELTA_SYM 0x7000001d /* Delta symbols that Delta - relocations refer to. */ -#define DT_MIPS_DELTA_SYM_NO 0x7000001e /* Number of entries in - DT_MIPS_DELTA_SYM. */ -#define DT_MIPS_DELTA_CLASSSYM 0x70000020 /* Delta symbols that hold the - class declaration. */ -#define DT_MIPS_DELTA_CLASSSYM_NO 0x70000021 /* Number of entries in - DT_MIPS_DELTA_CLASSSYM. */ -#define DT_MIPS_CXX_FLAGS 0x70000022 /* Flags indicating for C++ flavor. */ -#define DT_MIPS_PIXIE_INIT 0x70000023 -#define DT_MIPS_SYMBOL_LIB 0x70000024 -#define DT_MIPS_LOCALPAGE_GOTIDX 0x70000025 -#define DT_MIPS_LOCAL_GOTIDX 0x70000026 -#define DT_MIPS_HIDDEN_GOTIDX 0x70000027 -#define DT_MIPS_PROTECTED_GOTIDX 0x70000028 -#define DT_MIPS_OPTIONS 0x70000029 /* Address of .options. */ -#define DT_MIPS_INTERFACE 0x7000002a /* Address of .interface. */ -#define DT_MIPS_DYNSTR_ALIGN 0x7000002b -#define DT_MIPS_INTERFACE_SIZE 0x7000002c /* Size of the .interface section. */ -#define DT_MIPS_RLD_TEXT_RESOLVE_ADDR 0x7000002d /* Address of rld_text_rsolve - function stored in GOT. */ -#define DT_MIPS_PERF_SUFFIX 0x7000002e /* Default suffix of dso to be added - by rld on dlopen() calls. */ -#define DT_MIPS_COMPACT_SIZE 0x7000002f /* (O32)Size of compact rel section. */ -#define DT_MIPS_GP_VALUE 0x70000030 /* GP value for aux GOTs. */ -#define DT_MIPS_AUX_DYNAMIC 0x70000031 /* Address of aux .dynamic. */ -/* The address of .got.plt in an executable using the new non-PIC ABI. */ -#define DT_MIPS_PLTGOT 0x70000032 -/* The base of the PLT in an executable using the new non-PIC ABI if that - PLT is writable. For a non-writable PLT, this is omitted or has a zero - value. */ -#define DT_MIPS_RWPLT 0x70000034 -/* 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. */ - -#define RHF_NONE 0 /* No flags */ -#define RHF_QUICKSTART (1 << 0) /* Use quickstart */ -#define RHF_NOTPOT (1 << 1) /* Hash size not power of 2 */ -#define RHF_NO_LIBRARY_REPLACEMENT (1 << 2) /* Ignore LD_LIBRARY_PATH */ -#define RHF_NO_MOVE (1 << 3) -#define RHF_SGI_ONLY (1 << 4) -#define RHF_GUARANTEE_INIT (1 << 5) -#define RHF_DELTA_C_PLUS_PLUS (1 << 6) -#define RHF_GUARANTEE_START_INIT (1 << 7) -#define RHF_PIXIE (1 << 8) -#define RHF_DEFAULT_DELAY_LOAD (1 << 9) -#define RHF_REQUICKSTART (1 << 10) -#define RHF_REQUICKSTARTED (1 << 11) -#define RHF_CORD (1 << 12) -#define RHF_NO_UNRES_UNDEF (1 << 13) -#define RHF_RLD_ORDER_SAFE (1 << 14) - -/* Entries found in sections of type SHT_MIPS_LIBLIST. */ - -typedef struct -{ - Elf32_Word l_name; /* Name (string table index) */ - Elf32_Word l_time_stamp; /* Timestamp */ - Elf32_Word l_checksum; /* Checksum */ - Elf32_Word l_version; /* Interface version */ - Elf32_Word l_flags; /* Flags */ -} Elf32_Lib; - -typedef struct -{ - Elf64_Word l_name; /* Name (string table index) */ - Elf64_Word l_time_stamp; /* Timestamp */ - Elf64_Word l_checksum; /* Checksum */ - Elf64_Word l_version; /* Interface version */ - Elf64_Word l_flags; /* Flags */ -} Elf64_Lib; - - -/* Legal values for l_flags. */ - -#define LL_NONE 0 -#define LL_EXACT_MATCH (1 << 0) /* Require exact match */ -#define LL_IGNORE_INT_VER (1 << 1) /* Ignore interface version */ -#define LL_REQUIRE_MINOR (1 << 2) -#define LL_EXPORTS (1 << 3) -#define LL_DELAY_LOAD (1 << 4) -#define LL_DELTA (1 << 5) - -/* Entries found in sections of type SHT_MIPS_CONFLICT. */ - -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. */ - -/* Legal values for e_flags field of Elf32_Ehdr. */ - -#define EF_PARISC_TRAPNIL 0x00010000 /* Trap nil pointer dereference. */ -#define EF_PARISC_EXT 0x00020000 /* Program uses arch. extensions. */ -#define EF_PARISC_LSB 0x00040000 /* Program expects little endian. */ -#define EF_PARISC_WIDE 0x00080000 /* Program expects wide mode. */ -#define EF_PARISC_NO_KABP 0x00100000 /* No kernel assisted branch - prediction. */ -#define EF_PARISC_LAZYSWAP 0x00400000 /* Allow lazy swapping. */ -#define EF_PARISC_ARCH 0x0000ffff /* Architecture version. */ - -/* Defined values for `e_flags & EF_PARISC_ARCH' are: */ - -#define EFA_PARISC_1_0 0x020b /* PA-RISC 1.0 big-endian. */ -#define EFA_PARISC_1_1 0x0210 /* PA-RISC 1.1 big-endian. */ -#define EFA_PARISC_2_0 0x0214 /* PA-RISC 2.0 big-endian. */ - -/* Additional section indeces. */ - -#define SHN_PARISC_ANSI_COMMON 0xff00 /* Section for tenatively declared - symbols in ANSI C. */ -#define SHN_PARISC_HUGE_COMMON 0xff01 /* Common blocks in huge model. */ - -/* Legal values for sh_type field of Elf32_Shdr. */ - -#define SHT_PARISC_EXT 0x70000000 /* Contains product specific ext. */ -#define SHT_PARISC_UNWIND 0x70000001 /* Unwind information. */ -#define SHT_PARISC_DOC 0x70000002 /* Debug info for optimized code. */ - -/* Legal values for sh_flags field of Elf32_Shdr. */ - -#define SHF_PARISC_SHORT 0x20000000 /* Section with short addressing. */ -#define SHF_PARISC_HUGE 0x40000000 /* Section far from gp. */ -#define SHF_PARISC_SBP 0x80000000 /* Static branch prediction code. */ - -/* Legal values for ST_TYPE subfield of st_info (symbol type). */ - -#define STT_PARISC_MILLICODE 13 /* Millicode function entry point. */ - -#define STT_HP_OPAQUE (STT_LOOS + 0x1) -#define STT_HP_STUB (STT_LOOS + 0x2) - -/* HPPA relocs. */ - -#define R_PARISC_NONE 0 /* No reloc. */ -#define R_PARISC_DIR32 1 /* Direct 32-bit reference. */ -#define R_PARISC_DIR21L 2 /* Left 21 bits of eff. address. */ -#define R_PARISC_DIR17R 3 /* Right 17 bits of eff. address. */ -#define R_PARISC_DIR17F 4 /* 17 bits of eff. address. */ -#define R_PARISC_DIR14R 6 /* Right 14 bits of eff. address. */ -#define R_PARISC_PCREL32 9 /* 32-bit rel. address. */ -#define R_PARISC_PCREL21L 10 /* Left 21 bits of rel. address. */ -#define R_PARISC_PCREL17R 11 /* Right 17 bits of rel. address. */ -#define R_PARISC_PCREL17F 12 /* 17 bits of rel. address. */ -#define R_PARISC_PCREL14R 14 /* Right 14 bits of rel. address. */ -#define R_PARISC_DPREL21L 18 /* Left 21 bits of rel. address. */ -#define R_PARISC_DPREL14R 22 /* Right 14 bits of rel. address. */ -#define R_PARISC_GPREL21L 26 /* GP-relative, left 21 bits. */ -#define R_PARISC_GPREL14R 30 /* GP-relative, right 14 bits. */ -#define R_PARISC_LTOFF21L 34 /* LT-relative, left 21 bits. */ -#define R_PARISC_LTOFF14R 38 /* LT-relative, right 14 bits. */ -#define R_PARISC_SECREL32 41 /* 32 bits section rel. address. */ -#define R_PARISC_SEGBASE 48 /* No relocation, set segment base. */ -#define R_PARISC_SEGREL32 49 /* 32 bits segment rel. address. */ -#define R_PARISC_PLTOFF21L 50 /* PLT rel. address, left 21 bits. */ -#define R_PARISC_PLTOFF14R 54 /* PLT rel. address, right 14 bits. */ -#define R_PARISC_LTOFF_FPTR32 57 /* 32 bits LT-rel. function pointer. */ -#define R_PARISC_LTOFF_FPTR21L 58 /* LT-rel. fct ptr, left 21 bits. */ -#define R_PARISC_LTOFF_FPTR14R 62 /* LT-rel. fct ptr, right 14 bits. */ -#define R_PARISC_FPTR64 64 /* 64 bits function address. */ -#define R_PARISC_PLABEL32 65 /* 32 bits function address. */ -#define R_PARISC_PLABEL21L 66 /* Left 21 bits of fdesc address. */ -#define R_PARISC_PLABEL14R 70 /* Right 14 bits of fdesc address. */ -#define R_PARISC_PCREL64 72 /* 64 bits PC-rel. address. */ -#define R_PARISC_PCREL22F 74 /* 22 bits PC-rel. address. */ -#define R_PARISC_PCREL14WR 75 /* PC-rel. address, right 14 bits. */ -#define R_PARISC_PCREL14DR 76 /* PC rel. address, right 14 bits. */ -#define R_PARISC_PCREL16F 77 /* 16 bits PC-rel. address. */ -#define R_PARISC_PCREL16WF 78 /* 16 bits PC-rel. address. */ -#define R_PARISC_PCREL16DF 79 /* 16 bits PC-rel. address. */ -#define R_PARISC_DIR64 80 /* 64 bits of eff. address. */ -#define R_PARISC_DIR14WR 83 /* 14 bits of eff. address. */ -#define R_PARISC_DIR14DR 84 /* 14 bits of eff. address. */ -#define R_PARISC_DIR16F 85 /* 16 bits of eff. address. */ -#define R_PARISC_DIR16WF 86 /* 16 bits of eff. address. */ -#define R_PARISC_DIR16DF 87 /* 16 bits of eff. address. */ -#define R_PARISC_GPREL64 88 /* 64 bits of GP-rel. address. */ -#define R_PARISC_GPREL14WR 91 /* GP-rel. address, right 14 bits. */ -#define R_PARISC_GPREL14DR 92 /* GP-rel. address, right 14 bits. */ -#define R_PARISC_GPREL16F 93 /* 16 bits GP-rel. address. */ -#define R_PARISC_GPREL16WF 94 /* 16 bits GP-rel. address. */ -#define R_PARISC_GPREL16DF 95 /* 16 bits GP-rel. address. */ -#define R_PARISC_LTOFF64 96 /* 64 bits LT-rel. address. */ -#define R_PARISC_LTOFF14WR 99 /* LT-rel. address, right 14 bits. */ -#define R_PARISC_LTOFF14DR 100 /* LT-rel. address, right 14 bits. */ -#define R_PARISC_LTOFF16F 101 /* 16 bits LT-rel. address. */ -#define R_PARISC_LTOFF16WF 102 /* 16 bits LT-rel. address. */ -#define R_PARISC_LTOFF16DF 103 /* 16 bits LT-rel. address. */ -#define R_PARISC_SECREL64 104 /* 64 bits section rel. address. */ -#define R_PARISC_SEGREL64 112 /* 64 bits segment rel. address. */ -#define R_PARISC_PLTOFF14WR 115 /* PLT-rel. address, right 14 bits. */ -#define R_PARISC_PLTOFF14DR 116 /* PLT-rel. address, right 14 bits. */ -#define R_PARISC_PLTOFF16F 117 /* 16 bits LT-rel. address. */ -#define R_PARISC_PLTOFF16WF 118 /* 16 bits PLT-rel. address. */ -#define R_PARISC_PLTOFF16DF 119 /* 16 bits PLT-rel. address. */ -#define R_PARISC_LTOFF_FPTR64 120 /* 64 bits LT-rel. function ptr. */ -#define R_PARISC_LTOFF_FPTR14WR 123 /* LT-rel. fct. ptr., right 14 bits. */ -#define R_PARISC_LTOFF_FPTR14DR 124 /* LT-rel. fct. ptr., right 14 bits. */ -#define R_PARISC_LTOFF_FPTR16F 125 /* 16 bits LT-rel. function ptr. */ -#define R_PARISC_LTOFF_FPTR16WF 126 /* 16 bits LT-rel. function ptr. */ -#define R_PARISC_LTOFF_FPTR16DF 127 /* 16 bits LT-rel. function ptr. */ -#define R_PARISC_LORESERVE 128 -#define R_PARISC_COPY 128 /* Copy relocation. */ -#define R_PARISC_IPLT 129 /* Dynamic reloc, imported PLT */ -#define R_PARISC_EPLT 130 /* Dynamic reloc, exported PLT */ -#define R_PARISC_TPREL32 153 /* 32 bits TP-rel. address. */ -#define R_PARISC_TPREL21L 154 /* TP-rel. address, left 21 bits. */ -#define R_PARISC_TPREL14R 158 /* TP-rel. address, right 14 bits. */ -#define R_PARISC_LTOFF_TP21L 162 /* LT-TP-rel. address, left 21 bits. */ -#define R_PARISC_LTOFF_TP14R 166 /* LT-TP-rel. address, right 14 bits.*/ -#define R_PARISC_LTOFF_TP14F 167 /* 14 bits LT-TP-rel. address. */ -#define R_PARISC_TPREL64 216 /* 64 bits TP-rel. address. */ -#define R_PARISC_TPREL14WR 219 /* TP-rel. address, right 14 bits. */ -#define R_PARISC_TPREL14DR 220 /* TP-rel. address, right 14 bits. */ -#define R_PARISC_TPREL16F 221 /* 16 bits TP-rel. address. */ -#define R_PARISC_TPREL16WF 222 /* 16 bits TP-rel. address. */ -#define R_PARISC_TPREL16DF 223 /* 16 bits TP-rel. address. */ -#define R_PARISC_LTOFF_TP64 224 /* 64 bits LT-TP-rel. address. */ -#define R_PARISC_LTOFF_TP14WR 227 /* LT-TP-rel. address, right 14 bits.*/ -#define R_PARISC_LTOFF_TP14DR 228 /* LT-TP-rel. address, right 14 bits.*/ -#define R_PARISC_LTOFF_TP16F 229 /* 16 bits LT-TP-rel. address. */ -#define R_PARISC_LTOFF_TP16WF 230 /* 16 bits LT-TP-rel. address. */ -#define R_PARISC_LTOFF_TP16DF 231 /* 16 bits LT-TP-rel. address. */ -#define R_PARISC_GNU_VTENTRY 232 -#define R_PARISC_GNU_VTINHERIT 233 -#define R_PARISC_TLS_GD21L 234 /* GD 21-bit left. */ -#define R_PARISC_TLS_GD14R 235 /* GD 14-bit right. */ -#define R_PARISC_TLS_GDCALL 236 /* GD call to __t_g_a. */ -#define R_PARISC_TLS_LDM21L 237 /* LD module 21-bit left. */ -#define R_PARISC_TLS_LDM14R 238 /* LD module 14-bit right. */ -#define R_PARISC_TLS_LDMCALL 239 /* LD module call to __t_g_a. */ -#define R_PARISC_TLS_LDO21L 240 /* LD offset 21-bit left. */ -#define R_PARISC_TLS_LDO14R 241 /* LD offset 14-bit right. */ -#define R_PARISC_TLS_DTPMOD32 242 /* DTP module 32-bit. */ -#define R_PARISC_TLS_DTPMOD64 243 /* DTP module 64-bit. */ -#define R_PARISC_TLS_DTPOFF32 244 /* DTP offset 32-bit. */ -#define R_PARISC_TLS_DTPOFF64 245 /* DTP offset 32-bit. */ -#define R_PARISC_TLS_LE21L R_PARISC_TPREL21L -#define R_PARISC_TLS_LE14R R_PARISC_TPREL14R -#define R_PARISC_TLS_IE21L R_PARISC_LTOFF_TP21L -#define R_PARISC_TLS_IE14R R_PARISC_LTOFF_TP14R -#define R_PARISC_TLS_TPREL32 R_PARISC_TPREL32 -#define R_PARISC_TLS_TPREL64 R_PARISC_TPREL64 -#define R_PARISC_HIRESERVE 255 - -/* Legal values for p_type field of Elf32_Phdr/Elf64_Phdr. */ - -#define PT_HP_TLS (PT_LOOS + 0x0) -#define PT_HP_CORE_NONE (PT_LOOS + 0x1) -#define PT_HP_CORE_VERSION (PT_LOOS + 0x2) -#define PT_HP_CORE_KERNEL (PT_LOOS + 0x3) -#define PT_HP_CORE_COMM (PT_LOOS + 0x4) -#define PT_HP_CORE_PROC (PT_LOOS + 0x5) -#define PT_HP_CORE_LOADABLE (PT_LOOS + 0x6) -#define PT_HP_CORE_STACK (PT_LOOS + 0x7) -#define PT_HP_CORE_SHM (PT_LOOS + 0x8) -#define PT_HP_CORE_MMF (PT_LOOS + 0x9) -#define PT_HP_PARALLEL (PT_LOOS + 0x10) -#define PT_HP_FASTBIND (PT_LOOS + 0x11) -#define PT_HP_OPT_ANNOT (PT_LOOS + 0x12) -#define PT_HP_HSL_ANNOT (PT_LOOS + 0x13) -#define PT_HP_STACK (PT_LOOS + 0x14) - -#define PT_PARISC_ARCHEXT 0x70000000 -#define PT_PARISC_UNWIND 0x70000001 - -/* Legal values for p_flags field of Elf32_Phdr/Elf64_Phdr. */ - -#define PF_PARISC_SBP 0x08000000 - -#define PF_HP_PAGE_SIZE 0x00100000 -#define PF_HP_FAR_SHARED 0x00200000 -#define PF_HP_NEAR_SHARED 0x00400000 -#define PF_HP_CODE 0x01000000 -#define PF_HP_MODIFY 0x02000000 -#define PF_HP_LAZYSWAP 0x04000000 -#define PF_HP_SBP 0x08000000 - - -/* Alpha specific definitions. */ - -/* Legal values for e_flags field of Elf64_Ehdr. */ - -#define EF_ALPHA_32BIT 1 /* All addresses must be < 2GB. */ -#define EF_ALPHA_CANRELAX 2 /* Relocations for relaxing exist. */ - -/* Legal values for sh_type field of Elf64_Shdr. */ - -/* These two are primerily concerned with ECOFF debugging info. */ -#define SHT_ALPHA_DEBUG 0x70000001 -#define SHT_ALPHA_REGINFO 0x70000002 - -/* Legal values for sh_flags field of Elf64_Shdr. */ - -#define SHF_ALPHA_GPREL 0x10000000 - -/* Legal values for st_other field of Elf64_Sym. */ -#define STO_ALPHA_NOPV 0x80 /* No PV required. */ -#define STO_ALPHA_STD_GPLOAD 0x88 /* PV only used for initial ldgp. */ - -/* Alpha relocs. */ - -#define R_ALPHA_NONE 0 /* No reloc */ -#define R_ALPHA_REFLONG 1 /* Direct 32 bit */ -#define R_ALPHA_REFQUAD 2 /* Direct 64 bit */ -#define R_ALPHA_GPREL32 3 /* GP relative 32 bit */ -#define R_ALPHA_LITERAL 4 /* GP relative 16 bit w/optimization */ -#define R_ALPHA_LITUSE 5 /* Optimization hint for LITERAL */ -#define R_ALPHA_GPDISP 6 /* Add displacement to GP */ -#define R_ALPHA_BRADDR 7 /* PC+4 relative 23 bit shifted */ -#define R_ALPHA_HINT 8 /* PC+4 relative 16 bit shifted */ -#define R_ALPHA_SREL16 9 /* PC relative 16 bit */ -#define R_ALPHA_SREL32 10 /* PC relative 32 bit */ -#define R_ALPHA_SREL64 11 /* PC relative 64 bit */ -#define R_ALPHA_GPRELHIGH 17 /* GP relative 32 bit, high 16 bits */ -#define R_ALPHA_GPRELLOW 18 /* GP relative 32 bit, low 16 bits */ -#define R_ALPHA_GPREL16 19 /* GP relative 16 bit */ -#define R_ALPHA_COPY 24 /* Copy symbol at runtime */ -#define R_ALPHA_GLOB_DAT 25 /* Create GOT entry */ -#define R_ALPHA_JMP_SLOT 26 /* Create PLT entry */ -#define R_ALPHA_RELATIVE 27 /* Adjust by program base */ -#define R_ALPHA_TLS_GD_HI 28 -#define R_ALPHA_TLSGD 29 -#define R_ALPHA_TLS_LDM 30 -#define R_ALPHA_DTPMOD64 31 -#define R_ALPHA_GOTDTPREL 32 -#define R_ALPHA_DTPREL64 33 -#define R_ALPHA_DTPRELHI 34 -#define R_ALPHA_DTPRELLO 35 -#define R_ALPHA_DTPREL16 36 -#define R_ALPHA_GOTTPREL 37 -#define R_ALPHA_TPREL64 38 -#define R_ALPHA_TPRELHI 39 -#define R_ALPHA_TPRELLO 40 -#define R_ALPHA_TPREL16 41 -/* Keep this the last entry. */ -#define R_ALPHA_NUM 46 - -/* Magic values of the LITUSE relocation addend. */ -#define LITUSE_ALPHA_ADDR 0 -#define LITUSE_ALPHA_BASE 1 -#define LITUSE_ALPHA_BYTOFF 2 -#define LITUSE_ALPHA_JSR 3 -#define LITUSE_ALPHA_TLS_GD 4 -#define LITUSE_ALPHA_TLS_LDM 5 - -/* Legal values for d_tag of Elf64_Dyn. */ -#define DT_ALPHA_PLTRO (DT_LOPROC + 0) -#define DT_ALPHA_NUM 1 - -/* PowerPC specific declarations */ - -/* Values for Elf32/64_Ehdr.e_flags. */ -#define EF_PPC_EMB 0x80000000 /* PowerPC embedded flag */ - -/* Cygnus local bits below */ -#define EF_PPC_RELOCATABLE 0x00010000 /* PowerPC -mrelocatable flag*/ -#define EF_PPC_RELOCATABLE_LIB 0x00008000 /* PowerPC -mrelocatable-lib - flag */ - -/* PowerPC relocations defined by the ABIs */ -#define R_PPC_NONE 0 -#define R_PPC_ADDR32 1 /* 32bit absolute address */ -#define R_PPC_ADDR24 2 /* 26bit address, 2 bits ignored. */ -#define R_PPC_ADDR16 3 /* 16bit absolute address */ -#define R_PPC_ADDR16_LO 4 /* lower 16bit of absolute address */ -#define R_PPC_ADDR16_HI 5 /* high 16bit of absolute address */ -#define R_PPC_ADDR16_HA 6 /* adjusted high 16bit */ -#define R_PPC_ADDR14 7 /* 16bit address, 2 bits ignored */ -#define R_PPC_ADDR14_BRTAKEN 8 -#define R_PPC_ADDR14_BRNTAKEN 9 -#define R_PPC_REL24 10 /* PC relative 26 bit */ -#define R_PPC_REL14 11 /* PC relative 16 bit */ -#define R_PPC_REL14_BRTAKEN 12 -#define R_PPC_REL14_BRNTAKEN 13 -#define R_PPC_GOT16 14 -#define R_PPC_GOT16_LO 15 -#define R_PPC_GOT16_HI 16 -#define R_PPC_GOT16_HA 17 -#define R_PPC_PLTREL24 18 -#define R_PPC_COPY 19 -#define R_PPC_GLOB_DAT 20 -#define R_PPC_JMP_SLOT 21 -#define R_PPC_RELATIVE 22 -#define R_PPC_LOCAL24PC 23 -#define R_PPC_UADDR32 24 -#define R_PPC_UADDR16 25 -#define R_PPC_REL32 26 -#define R_PPC_PLT32 27 -#define R_PPC_PLTREL32 28 -#define R_PPC_PLT16_LO 29 -#define R_PPC_PLT16_HI 30 -#define R_PPC_PLT16_HA 31 -#define R_PPC_SDAREL16 32 -#define R_PPC_SECTOFF 33 -#define R_PPC_SECTOFF_LO 34 -#define R_PPC_SECTOFF_HI 35 -#define R_PPC_SECTOFF_HA 36 - -/* PowerPC relocations defined for the TLS access ABI. */ -#define R_PPC_TLS 67 /* none (sym+add)@tls */ -#define R_PPC_DTPMOD32 68 /* word32 (sym+add)@dtpmod */ -#define R_PPC_TPREL16 69 /* half16* (sym+add)@tprel */ -#define R_PPC_TPREL16_LO 70 /* half16 (sym+add)@tprel@l */ -#define R_PPC_TPREL16_HI 71 /* half16 (sym+add)@tprel@h */ -#define R_PPC_TPREL16_HA 72 /* half16 (sym+add)@tprel@ha */ -#define R_PPC_TPREL32 73 /* word32 (sym+add)@tprel */ -#define R_PPC_DTPREL16 74 /* half16* (sym+add)@dtprel */ -#define R_PPC_DTPREL16_LO 75 /* half16 (sym+add)@dtprel@l */ -#define R_PPC_DTPREL16_HI 76 /* half16 (sym+add)@dtprel@h */ -#define R_PPC_DTPREL16_HA 77 /* half16 (sym+add)@dtprel@ha */ -#define R_PPC_DTPREL32 78 /* word32 (sym+add)@dtprel */ -#define R_PPC_GOT_TLSGD16 79 /* half16* (sym+add)@got@tlsgd */ -#define R_PPC_GOT_TLSGD16_LO 80 /* half16 (sym+add)@got@tlsgd@l */ -#define R_PPC_GOT_TLSGD16_HI 81 /* half16 (sym+add)@got@tlsgd@h */ -#define R_PPC_GOT_TLSGD16_HA 82 /* half16 (sym+add)@got@tlsgd@ha */ -#define R_PPC_GOT_TLSLD16 83 /* half16* (sym+add)@got@tlsld */ -#define R_PPC_GOT_TLSLD16_LO 84 /* half16 (sym+add)@got@tlsld@l */ -#define R_PPC_GOT_TLSLD16_HI 85 /* half16 (sym+add)@got@tlsld@h */ -#define R_PPC_GOT_TLSLD16_HA 86 /* half16 (sym+add)@got@tlsld@ha */ -#define R_PPC_GOT_TPREL16 87 /* half16* (sym+add)@got@tprel */ -#define R_PPC_GOT_TPREL16_LO 88 /* half16 (sym+add)@got@tprel@l */ -#define R_PPC_GOT_TPREL16_HI 89 /* half16 (sym+add)@got@tprel@h */ -#define R_PPC_GOT_TPREL16_HA 90 /* half16 (sym+add)@got@tprel@ha */ -#define R_PPC_GOT_DTPREL16 91 /* half16* (sym+add)@got@dtprel */ -#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. */ -#define R_PPC_EMB_NADDR32 101 -#define R_PPC_EMB_NADDR16 102 -#define R_PPC_EMB_NADDR16_LO 103 -#define R_PPC_EMB_NADDR16_HI 104 -#define R_PPC_EMB_NADDR16_HA 105 -#define R_PPC_EMB_SDAI16 106 -#define R_PPC_EMB_SDA2I16 107 -#define R_PPC_EMB_SDA2REL 108 -#define R_PPC_EMB_SDA21 109 /* 16 bit offset in SDA */ -#define R_PPC_EMB_MRKREF 110 -#define R_PPC_EMB_RELSEC16 111 -#define R_PPC_EMB_RELST_LO 112 -#define R_PPC_EMB_RELST_HI 113 -#define R_PPC_EMB_RELST_HA 114 -#define R_PPC_EMB_BIT_FLD 115 -#define R_PPC_EMB_RELSDA 116 /* 16 bit relative offset in SDA */ - -/* Diab tool relocations. */ -#define R_PPC_DIAB_SDA21_LO 180 /* like EMB_SDA21, but lower 16 bit */ -#define R_PPC_DIAB_SDA21_HI 181 /* like EMB_SDA21, but high 16 bit */ -#define R_PPC_DIAB_SDA21_HA 182 /* like EMB_SDA21, adjusted high 16 */ -#define R_PPC_DIAB_RELSDA_LO 183 /* like EMB_RELSDA, but lower 16 bit */ -#define R_PPC_DIAB_RELSDA_HI 184 /* like EMB_RELSDA, but high 16 bit */ -#define R_PPC_DIAB_RELSDA_HA 185 /* like EMB_RELSDA, adjusted high 16 */ - -/* GNU extension to support local ifunc. */ -#define R_PPC_IRELATIVE 248 - -/* GNU relocs used in PIC code sequences. */ -#define R_PPC_REL16 249 /* half16 (sym+add-.) */ -#define R_PPC_REL16_LO 250 /* half16 (sym+add-.)@l */ -#define R_PPC_REL16_HI 251 /* half16 (sym+add-.)@h */ -#define R_PPC_REL16_HA 252 /* half16 (sym+add-.)@ha */ - -/* This is a phony reloc to handle any old fashioned TOC16 references - that may still be in object files. */ -#define R_PPC_TOC16 255 - -/* PowerPC specific values for the Dyn d_tag field. */ -#define DT_PPC_GOT (DT_LOPROC + 0) -#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 -#define R_PPC64_ADDR32 R_PPC_ADDR32 /* 32bit absolute address */ -#define R_PPC64_ADDR24 R_PPC_ADDR24 /* 26bit address, word aligned */ -#define R_PPC64_ADDR16 R_PPC_ADDR16 /* 16bit absolute address */ -#define R_PPC64_ADDR16_LO R_PPC_ADDR16_LO /* lower 16bits of address */ -#define R_PPC64_ADDR16_HI R_PPC_ADDR16_HI /* high 16bits of address. */ -#define R_PPC64_ADDR16_HA R_PPC_ADDR16_HA /* adjusted high 16bits. */ -#define R_PPC64_ADDR14 R_PPC_ADDR14 /* 16bit address, word aligned */ -#define R_PPC64_ADDR14_BRTAKEN R_PPC_ADDR14_BRTAKEN -#define R_PPC64_ADDR14_BRNTAKEN R_PPC_ADDR14_BRNTAKEN -#define R_PPC64_REL24 R_PPC_REL24 /* PC-rel. 26 bit, word aligned */ -#define R_PPC64_REL14 R_PPC_REL14 /* PC relative 16 bit */ -#define R_PPC64_REL14_BRTAKEN R_PPC_REL14_BRTAKEN -#define R_PPC64_REL14_BRNTAKEN R_PPC_REL14_BRNTAKEN -#define R_PPC64_GOT16 R_PPC_GOT16 -#define R_PPC64_GOT16_LO R_PPC_GOT16_LO -#define R_PPC64_GOT16_HI R_PPC_GOT16_HI -#define R_PPC64_GOT16_HA R_PPC_GOT16_HA - -#define R_PPC64_COPY R_PPC_COPY -#define R_PPC64_GLOB_DAT R_PPC_GLOB_DAT -#define R_PPC64_JMP_SLOT R_PPC_JMP_SLOT -#define R_PPC64_RELATIVE R_PPC_RELATIVE - -#define R_PPC64_UADDR32 R_PPC_UADDR32 -#define R_PPC64_UADDR16 R_PPC_UADDR16 -#define R_PPC64_REL32 R_PPC_REL32 -#define R_PPC64_PLT32 R_PPC_PLT32 -#define R_PPC64_PLTREL32 R_PPC_PLTREL32 -#define R_PPC64_PLT16_LO R_PPC_PLT16_LO -#define R_PPC64_PLT16_HI R_PPC_PLT16_HI -#define R_PPC64_PLT16_HA R_PPC_PLT16_HA - -#define R_PPC64_SECTOFF R_PPC_SECTOFF -#define R_PPC64_SECTOFF_LO R_PPC_SECTOFF_LO -#define R_PPC64_SECTOFF_HI R_PPC_SECTOFF_HI -#define R_PPC64_SECTOFF_HA R_PPC_SECTOFF_HA -#define R_PPC64_ADDR30 37 /* word30 (S + A - P) >> 2 */ -#define R_PPC64_ADDR64 38 /* doubleword64 S + A */ -#define R_PPC64_ADDR16_HIGHER 39 /* half16 #higher(S + A) */ -#define R_PPC64_ADDR16_HIGHERA 40 /* half16 #highera(S + A) */ -#define R_PPC64_ADDR16_HIGHEST 41 /* half16 #highest(S + A) */ -#define R_PPC64_ADDR16_HIGHESTA 42 /* half16 #highesta(S + A) */ -#define R_PPC64_UADDR64 43 /* doubleword64 S + A */ -#define R_PPC64_REL64 44 /* doubleword64 S + A - P */ -#define R_PPC64_PLT64 45 /* doubleword64 L + A */ -#define R_PPC64_PLTREL64 46 /* doubleword64 L + A - P */ -#define R_PPC64_TOC16 47 /* half16* S + A - .TOC */ -#define R_PPC64_TOC16_LO 48 /* half16 #lo(S + A - .TOC.) */ -#define R_PPC64_TOC16_HI 49 /* half16 #hi(S + A - .TOC.) */ -#define R_PPC64_TOC16_HA 50 /* half16 #ha(S + A - .TOC.) */ -#define R_PPC64_TOC 51 /* doubleword64 .TOC */ -#define R_PPC64_PLTGOT16 52 /* half16* M + A */ -#define R_PPC64_PLTGOT16_LO 53 /* half16 #lo(M + A) */ -#define R_PPC64_PLTGOT16_HI 54 /* half16 #hi(M + A) */ -#define R_PPC64_PLTGOT16_HA 55 /* half16 #ha(M + A) */ - -#define R_PPC64_ADDR16_DS 56 /* half16ds* (S + A) >> 2 */ -#define R_PPC64_ADDR16_LO_DS 57 /* half16ds #lo(S + A) >> 2 */ -#define R_PPC64_GOT16_DS 58 /* half16ds* (G + A) >> 2 */ -#define R_PPC64_GOT16_LO_DS 59 /* half16ds #lo(G + A) >> 2 */ -#define R_PPC64_PLT16_LO_DS 60 /* half16ds #lo(L + A) >> 2 */ -#define R_PPC64_SECTOFF_DS 61 /* half16ds* (R + A) >> 2 */ -#define R_PPC64_SECTOFF_LO_DS 62 /* half16ds #lo(R + A) >> 2 */ -#define R_PPC64_TOC16_DS 63 /* half16ds* (S + A - .TOC.) >> 2 */ -#define R_PPC64_TOC16_LO_DS 64 /* half16ds #lo(S + A - .TOC.) >> 2 */ -#define R_PPC64_PLTGOT16_DS 65 /* half16ds* (M + A) >> 2 */ -#define R_PPC64_PLTGOT16_LO_DS 66 /* half16ds #lo(M + A) >> 2 */ - -/* PowerPC64 relocations defined for the TLS access ABI. */ -#define R_PPC64_TLS 67 /* none (sym+add)@tls */ -#define R_PPC64_DTPMOD64 68 /* doubleword64 (sym+add)@dtpmod */ -#define R_PPC64_TPREL16 69 /* half16* (sym+add)@tprel */ -#define R_PPC64_TPREL16_LO 70 /* half16 (sym+add)@tprel@l */ -#define R_PPC64_TPREL16_HI 71 /* half16 (sym+add)@tprel@h */ -#define R_PPC64_TPREL16_HA 72 /* half16 (sym+add)@tprel@ha */ -#define R_PPC64_TPREL64 73 /* doubleword64 (sym+add)@tprel */ -#define R_PPC64_DTPREL16 74 /* half16* (sym+add)@dtprel */ -#define R_PPC64_DTPREL16_LO 75 /* half16 (sym+add)@dtprel@l */ -#define R_PPC64_DTPREL16_HI 76 /* half16 (sym+add)@dtprel@h */ -#define R_PPC64_DTPREL16_HA 77 /* half16 (sym+add)@dtprel@ha */ -#define R_PPC64_DTPREL64 78 /* doubleword64 (sym+add)@dtprel */ -#define R_PPC64_GOT_TLSGD16 79 /* half16* (sym+add)@got@tlsgd */ -#define R_PPC64_GOT_TLSGD16_LO 80 /* half16 (sym+add)@got@tlsgd@l */ -#define R_PPC64_GOT_TLSGD16_HI 81 /* half16 (sym+add)@got@tlsgd@h */ -#define R_PPC64_GOT_TLSGD16_HA 82 /* half16 (sym+add)@got@tlsgd@ha */ -#define R_PPC64_GOT_TLSLD16 83 /* half16* (sym+add)@got@tlsld */ -#define R_PPC64_GOT_TLSLD16_LO 84 /* half16 (sym+add)@got@tlsld@l */ -#define R_PPC64_GOT_TLSLD16_HI 85 /* half16 (sym+add)@got@tlsld@h */ -#define R_PPC64_GOT_TLSLD16_HA 86 /* half16 (sym+add)@got@tlsld@ha */ -#define R_PPC64_GOT_TPREL16_DS 87 /* half16ds* (sym+add)@got@tprel */ -#define R_PPC64_GOT_TPREL16_LO_DS 88 /* half16ds (sym+add)@got@tprel@l */ -#define R_PPC64_GOT_TPREL16_HI 89 /* half16 (sym+add)@got@tprel@h */ -#define R_PPC64_GOT_TPREL16_HA 90 /* half16 (sym+add)@got@tprel@ha */ -#define R_PPC64_GOT_DTPREL16_DS 91 /* half16ds* (sym+add)@got@dtprel */ -#define R_PPC64_GOT_DTPREL16_LO_DS 92 /* half16ds (sym+add)@got@dtprel@l */ -#define R_PPC64_GOT_DTPREL16_HI 93 /* half16 (sym+add)@got@dtprel@h */ -#define R_PPC64_GOT_DTPREL16_HA 94 /* half16 (sym+add)@got@dtprel@ha */ -#define R_PPC64_TPREL16_DS 95 /* half16ds* (sym+add)@tprel */ -#define R_PPC64_TPREL16_LO_DS 96 /* half16ds (sym+add)@tprel@l */ -#define R_PPC64_TPREL16_HIGHER 97 /* half16 (sym+add)@tprel@higher */ -#define R_PPC64_TPREL16_HIGHERA 98 /* half16 (sym+add)@tprel@highera */ -#define R_PPC64_TPREL16_HIGHEST 99 /* half16 (sym+add)@tprel@highest */ -#define R_PPC64_TPREL16_HIGHESTA 100 /* half16 (sym+add)@tprel@highesta */ -#define R_PPC64_DTPREL16_DS 101 /* half16ds* (sym+add)@dtprel */ -#define R_PPC64_DTPREL16_LO_DS 102 /* half16ds (sym+add)@dtprel@l */ -#define R_PPC64_DTPREL16_HIGHER 103 /* half16 (sym+add)@dtprel@higher */ -#define R_PPC64_DTPREL16_HIGHERA 104 /* half16 (sym+add)@dtprel@highera */ -#define R_PPC64_DTPREL16_HIGHEST 105 /* half16 (sym+add)@dtprel@highest */ -#define R_PPC64_DTPREL16_HIGHESTA 106 /* half16 (sym+add)@dtprel@highesta */ -#define R_PPC64_TLSGD 107 /* none (sym+add)@tlsgd */ -#define R_PPC64_TLSLD 108 /* none (sym+add)@tlsld */ -#define R_PPC64_TOCSAVE 109 /* none */ - -/* Added when HA and HI relocs were changed to report overflows. */ -#define R_PPC64_ADDR16_HIGH 110 -#define R_PPC64_ADDR16_HIGHA 111 -#define R_PPC64_TPREL16_HIGH 112 -#define R_PPC64_TPREL16_HIGHA 113 -#define R_PPC64_DTPREL16_HIGH 114 -#define R_PPC64_DTPREL16_HIGHA 115 - -/* GNU extension to support local ifunc. */ -#define R_PPC64_JMP_IREL 247 -#define R_PPC64_IRELATIVE 248 -#define R_PPC64_REL16 249 /* half16 (sym+add-.) */ -#define R_PPC64_REL16_LO 250 /* half16 (sym+add-.)@l */ -#define R_PPC64_REL16_HI 251 /* half16 (sym+add-.)@h */ -#define R_PPC64_REL16_HA 252 /* half16 (sym+add-.)@ha */ - -/* e_flags bits specifying ABI. - 1 for original function descriptor using ABI, - 2 for revised ABI without function descriptors, - 0 for unspecified or not using any features affected by the differences. */ -#define EF_PPC64_ABI 3 - -/* PowerPC64 specific values for the Dyn d_tag field. */ -#define DT_PPC64_GLINK (DT_LOPROC + 0) -#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 4 - -/* PowerPC64 specific values for the DT_PPC64_OPT Dyn entry. */ -#define PPC64_OPT_TLS 1 -#define PPC64_OPT_MULTI_TOC 2 - -/* PowerPC64 specific values for the Elf64_Sym st_other field. */ -#define STO_PPC64_LOCAL_BIT 5 -#define STO_PPC64_LOCAL_MASK (7 << STO_PPC64_LOCAL_BIT) -#define PPC64_LOCAL_ENTRY_OFFSET(other) \ - (((1 << (((other) & STO_PPC64_LOCAL_MASK) >> STO_PPC64_LOCAL_BIT)) >> 2) << 2) - - -/* ARM specific declarations */ - -/* Processor specific flags for the ELF header e_flags field. */ -#define EF_ARM_RELEXEC 0x01 -#define EF_ARM_HASENTRY 0x02 -#define EF_ARM_INTERWORK 0x04 -#define EF_ARM_APCS_26 0x08 -#define EF_ARM_APCS_FLOAT 0x10 -#define EF_ARM_PIC 0x20 -#define EF_ARM_ALIGN8 0x40 /* 8-bit structure alignment is in use */ -#define EF_ARM_NEW_ABI 0x80 -#define EF_ARM_OLD_ABI 0x100 -#define EF_ARM_SOFT_FLOAT 0x200 -#define EF_ARM_VFP_FLOAT 0x400 -#define EF_ARM_MAVERICK_FLOAT 0x800 - -#define EF_ARM_ABI_FLOAT_SOFT 0x200 /* NB conflicts with EF_ARM_SOFT_FLOAT */ -#define EF_ARM_ABI_FLOAT_HARD 0x400 /* NB conflicts with EF_ARM_VFP_FLOAT */ - - -/* Other constants defined in the ARM ELF spec. version B-01. */ -/* NB. These conflict with values defined above. */ -#define EF_ARM_SYMSARESORTED 0x04 -#define EF_ARM_DYNSYMSUSESEGIDX 0x08 -#define EF_ARM_MAPSYMSFIRST 0x10 -#define EF_ARM_EABIMASK 0XFF000000 - -/* Constants defined in AAELF. */ -#define EF_ARM_BE8 0x00800000 -#define EF_ARM_LE8 0x00400000 - -#define EF_ARM_EABI_VERSION(flags) ((flags) & EF_ARM_EABIMASK) -#define EF_ARM_EABI_UNKNOWN 0x00000000 -#define EF_ARM_EABI_VER1 0x01000000 -#define EF_ARM_EABI_VER2 0x02000000 -#define EF_ARM_EABI_VER3 0x03000000 -#define EF_ARM_EABI_VER4 0x04000000 -#define EF_ARM_EABI_VER5 0x05000000 - -/* Additional symbol types for Thumb. */ -#define STT_ARM_TFUNC STT_LOPROC /* A Thumb function. */ -#define STT_ARM_16BIT STT_HIPROC /* A Thumb label. */ - -/* ARM-specific values for sh_flags */ -#define SHF_ARM_ENTRYSECT 0x10000000 /* Section contains an entry point */ -#define SHF_ARM_COMDEF 0x80000000 /* Section may be multiply defined - in the input to a link step. */ - -/* ARM-specific program header flags */ -#define PF_ARM_SB 0x10000000 /* Segment contains the location - addressed by the static base. */ -#define PF_ARM_PI 0x20000000 /* Position-independent segment. */ -#define PF_ARM_ABS 0x40000000 /* Absolute segment. */ - -/* Processor specific values for the Phdr p_type field. */ -#define PT_ARM_EXIDX (PT_LOPROC + 1) /* ARM unwind segment. */ - -/* Processor specific values for the Shdr sh_type field. */ -#define SHT_ARM_EXIDX (SHT_LOPROC + 1) /* ARM unwind section. */ -#define SHT_ARM_PREEMPTMAP (SHT_LOPROC + 2) /* Preemption details. */ -#define SHT_ARM_ATTRIBUTES (SHT_LOPROC + 3) /* ARM attributes section. */ - - -/* 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. */ -#define R_AARCH64_PREL64 260 /* PC-relative 64-bit. */ -#define R_AARCH64_PREL32 261 /* PC-relative 32-bit. */ -#define R_AARCH64_PREL16 262 /* PC-relative 16-bit. */ -#define R_AARCH64_MOVW_UABS_G0 263 /* Dir. MOVZ imm. from bits 15:0. */ -#define R_AARCH64_MOVW_UABS_G0_NC 264 /* Likewise for MOVK; no check. */ -#define R_AARCH64_MOVW_UABS_G1 265 /* Dir. MOVZ imm. from bits 31:16. */ -#define R_AARCH64_MOVW_UABS_G1_NC 266 /* Likewise for MOVK; no check. */ -#define R_AARCH64_MOVW_UABS_G2 267 /* Dir. MOVZ imm. from bits 47:32. */ -#define R_AARCH64_MOVW_UABS_G2_NC 268 /* Likewise for MOVK; no check. */ -#define R_AARCH64_MOVW_UABS_G3 269 /* Dir. MOV{K,Z} imm. from 63:48. */ -#define R_AARCH64_MOVW_SABS_G0 270 /* Dir. MOV{N,Z} imm. from 15:0. */ -#define R_AARCH64_MOVW_SABS_G1 271 /* Dir. MOV{N,Z} imm. from 31:16. */ -#define R_AARCH64_MOVW_SABS_G2 272 /* Dir. MOV{N,Z} imm. from 47:32. */ -#define R_AARCH64_LD_PREL_LO19 273 /* PC-rel. LD imm. from bits 20:2. */ -#define R_AARCH64_ADR_PREL_LO21 274 /* PC-rel. ADR imm. from bits 20:0. */ -#define R_AARCH64_ADR_PREL_PG_HI21 275 /* Page-rel. ADRP imm. from 32:12. */ -#define R_AARCH64_ADR_PREL_PG_HI21_NC 276 /* Likewise; no overflow check. */ -#define R_AARCH64_ADD_ABS_LO12_NC 277 /* Dir. ADD imm. from bits 11:0. */ -#define R_AARCH64_LDST8_ABS_LO12_NC 278 /* Likewise for LD/ST; no check. */ -#define R_AARCH64_TSTBR14 279 /* PC-rel. TBZ/TBNZ imm. from 15:2. */ -#define R_AARCH64_CONDBR19 280 /* PC-rel. cond. br. imm. from 20:2. */ -#define R_AARCH64_JUMP26 282 /* PC-rel. B imm. from bits 27:2. */ -#define R_AARCH64_CALL26 283 /* Likewise for CALL. */ -#define R_AARCH64_LDST16_ABS_LO12_NC 284 /* Dir. ADD imm. from bits 11:1. */ -#define R_AARCH64_LDST32_ABS_LO12_NC 285 /* Likewise for bits 11:2. */ -#define R_AARCH64_LDST64_ABS_LO12_NC 286 /* Likewise for bits 11:3. */ -#define R_AARCH64_MOVW_PREL_G0 287 /* PC-rel. MOV{N,Z} imm. from 15:0. */ -#define R_AARCH64_MOVW_PREL_G0_NC 288 /* Likewise for MOVK; no check. */ -#define R_AARCH64_MOVW_PREL_G1 289 /* PC-rel. MOV{N,Z} imm. from 31:16. */ -#define R_AARCH64_MOVW_PREL_G1_NC 290 /* Likewise for MOVK; no check. */ -#define R_AARCH64_MOVW_PREL_G2 291 /* PC-rel. MOV{N,Z} imm. from 47:32. */ -#define R_AARCH64_MOVW_PREL_G2_NC 292 /* Likewise for MOVK; no check. */ -#define R_AARCH64_MOVW_PREL_G3 293 /* PC-rel. MOV{N,Z} imm. from 63:48. */ -#define R_AARCH64_LDST128_ABS_LO12_NC 299 /* Dir. ADD imm. from bits 11:4. */ -#define R_AARCH64_MOVW_GOTOFF_G0 300 /* GOT-rel. off. MOV{N,Z} imm. 15:0. */ -#define R_AARCH64_MOVW_GOTOFF_G0_NC 301 /* Likewise for MOVK; no check. */ -#define R_AARCH64_MOVW_GOTOFF_G1 302 /* GOT-rel. o. MOV{N,Z} imm. 31:16. */ -#define R_AARCH64_MOVW_GOTOFF_G1_NC 303 /* Likewise for MOVK; no check. */ -#define R_AARCH64_MOVW_GOTOFF_G2 304 /* GOT-rel. o. MOV{N,Z} imm. 47:32. */ -#define R_AARCH64_MOVW_GOTOFF_G2_NC 305 /* Likewise for MOVK; no check. */ -#define R_AARCH64_MOVW_GOTOFF_G3 306 /* GOT-rel. o. MOV{N,Z} imm. 63:48. */ -#define R_AARCH64_GOTREL64 307 /* GOT-relative 64-bit. */ -#define R_AARCH64_GOTREL32 308 /* GOT-relative 32-bit. */ -#define R_AARCH64_GOT_LD_PREL19 309 /* PC-rel. GOT off. load imm. 20:2. */ -#define R_AARCH64_LD64_GOTOFF_LO15 310 /* GOT-rel. off. LD/ST imm. 14:3. */ -#define R_AARCH64_ADR_GOT_PAGE 311 /* P-page-rel. GOT off. ADRP 32:12. */ -#define R_AARCH64_LD64_GOT_LO12_NC 312 /* Dir. GOT off. LD/ST imm. 11:3. */ -#define R_AARCH64_LD64_GOTPAGE_LO15 313 /* GOT-page-rel. GOT off. LD/ST 14:3 */ -#define R_AARCH64_TLSGD_ADR_PREL21 512 /* PC-relative ADR imm. 20:0. */ -#define R_AARCH64_TLSGD_ADR_PAGE21 513 /* page-rel. ADRP imm. 32:12. */ -#define R_AARCH64_TLSGD_ADD_LO12_NC 514 /* direct ADD imm. from 11:0. */ -#define R_AARCH64_TLSGD_MOVW_G1 515 /* GOT-rel. MOV{N,Z} 31:16. */ -#define R_AARCH64_TLSGD_MOVW_G0_NC 516 /* GOT-rel. MOVK imm. 15:0. */ -#define R_AARCH64_TLSLD_ADR_PREL21 517 /* Like 512; local dynamic model. */ -#define R_AARCH64_TLSLD_ADR_PAGE21 518 /* Like 513; local dynamic model. */ -#define R_AARCH64_TLSLD_ADD_LO12_NC 519 /* Like 514; local dynamic model. */ -#define R_AARCH64_TLSLD_MOVW_G1 520 /* Like 515; local dynamic model. */ -#define R_AARCH64_TLSLD_MOVW_G0_NC 521 /* Like 516; local dynamic model. */ -#define R_AARCH64_TLSLD_LD_PREL19 522 /* TLS PC-rel. load imm. 20:2. */ -#define R_AARCH64_TLSLD_MOVW_DTPREL_G2 523 /* TLS DTP-rel. MOV{N,Z} 47:32. */ -#define R_AARCH64_TLSLD_MOVW_DTPREL_G1 524 /* TLS DTP-rel. MOV{N,Z} 31:16. */ -#define R_AARCH64_TLSLD_MOVW_DTPREL_G1_NC 525 /* Likewise; MOVK; no check. */ -#define R_AARCH64_TLSLD_MOVW_DTPREL_G0 526 /* TLS DTP-rel. MOV{N,Z} 15:0. */ -#define R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC 527 /* Likewise; MOVK; no check. */ -#define R_AARCH64_TLSLD_ADD_DTPREL_HI12 528 /* DTP-rel. ADD imm. from 23:12. */ -#define R_AARCH64_TLSLD_ADD_DTPREL_LO12 529 /* DTP-rel. ADD imm. from 11:0. */ -#define R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC 530 /* Likewise; no ovfl. check. */ -#define R_AARCH64_TLSLD_LDST8_DTPREL_LO12 531 /* DTP-rel. LD/ST imm. 11:0. */ -#define R_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC 532 /* Likewise; no check. */ -#define R_AARCH64_TLSLD_LDST16_DTPREL_LO12 533 /* DTP-rel. LD/ST imm. 11:1. */ -#define R_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC 534 /* Likewise; no check. */ -#define R_AARCH64_TLSLD_LDST32_DTPREL_LO12 535 /* DTP-rel. LD/ST imm. 11:2. */ -#define R_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC 536 /* Likewise; no check. */ -#define R_AARCH64_TLSLD_LDST64_DTPREL_LO12 537 /* DTP-rel. LD/ST imm. 11:3. */ -#define R_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC 538 /* Likewise; no check. */ -#define R_AARCH64_TLSIE_MOVW_GOTTPREL_G1 539 /* GOT-rel. MOV{N,Z} 31:16. */ -#define R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC 540 /* GOT-rel. MOVK 15:0. */ -#define R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 541 /* Page-rel. ADRP 32:12. */ -#define R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC 542 /* Direct LD off. 11:3. */ -#define R_AARCH64_TLSIE_LD_GOTTPREL_PREL19 543 /* PC-rel. load imm. 20:2. */ -#define R_AARCH64_TLSLE_MOVW_TPREL_G2 544 /* TLS TP-rel. MOV{N,Z} 47:32. */ -#define R_AARCH64_TLSLE_MOVW_TPREL_G1 545 /* TLS TP-rel. MOV{N,Z} 31:16. */ -#define R_AARCH64_TLSLE_MOVW_TPREL_G1_NC 546 /* Likewise; MOVK; no check. */ -#define R_AARCH64_TLSLE_MOVW_TPREL_G0 547 /* TLS TP-rel. MOV{N,Z} 15:0. */ -#define R_AARCH64_TLSLE_MOVW_TPREL_G0_NC 548 /* Likewise; MOVK; no check. */ -#define R_AARCH64_TLSLE_ADD_TPREL_HI12 549 /* TP-rel. ADD imm. 23:12. */ -#define R_AARCH64_TLSLE_ADD_TPREL_LO12 550 /* TP-rel. ADD imm. 11:0. */ -#define R_AARCH64_TLSLE_ADD_TPREL_LO12_NC 551 /* Likewise; no ovfl. check. */ -#define R_AARCH64_TLSLE_LDST8_TPREL_LO12 552 /* TP-rel. LD/ST off. 11:0. */ -#define R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC 553 /* Likewise; no ovfl. check. */ -#define R_AARCH64_TLSLE_LDST16_TPREL_LO12 554 /* TP-rel. LD/ST off. 11:1. */ -#define R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC 555 /* Likewise; no check. */ -#define R_AARCH64_TLSLE_LDST32_TPREL_LO12 556 /* TP-rel. LD/ST off. 11:2. */ -#define R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC 557 /* Likewise; no check. */ -#define R_AARCH64_TLSLE_LDST64_TPREL_LO12 558 /* TP-rel. LD/ST off. 11:3. */ -#define R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC 559 /* Likewise; no check. */ -#define R_AARCH64_TLSDESC_LD_PREL19 560 /* PC-rel. load immediate 20:2. */ -#define R_AARCH64_TLSDESC_ADR_PREL21 561 /* PC-rel. ADR immediate 20:0. */ -#define R_AARCH64_TLSDESC_ADR_PAGE21 562 /* Page-rel. ADRP imm. 32:12. */ -#define R_AARCH64_TLSDESC_LD64_LO12 563 /* Direct LD off. from 11:3. */ -#define R_AARCH64_TLSDESC_ADD_LO12 564 /* Direct ADD imm. from 11:0. */ -#define R_AARCH64_TLSDESC_OFF_G1 565 /* GOT-rel. MOV{N,Z} imm. 31:16. */ -#define R_AARCH64_TLSDESC_OFF_G0_NC 566 /* GOT-rel. MOVK imm. 15:0; no ck. */ -#define R_AARCH64_TLSDESC_LDR 567 /* Relax LDR. */ -#define R_AARCH64_TLSDESC_ADD 568 /* Relax ADD. */ -#define R_AARCH64_TLSDESC_CALL 569 /* Relax BLR. */ -#define R_AARCH64_TLSLE_LDST128_TPREL_LO12 570 /* TP-rel. LD/ST off. 11:4. */ -#define R_AARCH64_TLSLE_LDST128_TPREL_LO12_NC 571 /* Likewise; no check. */ -#define R_AARCH64_TLSLD_LDST128_DTPREL_LO12 572 /* DTP-rel. LD/ST imm. 11:4. */ -#define R_AARCH64_TLSLD_LDST128_DTPREL_LO12_NC 573 /* Likewise; no check. */ -#define R_AARCH64_COPY 1024 /* Copy symbol at runtime. */ -#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_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. */ - -/* ARM relocs. */ - -#define R_ARM_NONE 0 /* No reloc */ -#define R_ARM_PC24 1 /* Deprecated PC relative 26 - bit branch. */ -#define R_ARM_ABS32 2 /* Direct 32 bit */ -#define R_ARM_REL32 3 /* PC relative 32 bit */ -#define R_ARM_PC13 4 -#define R_ARM_ABS16 5 /* Direct 16 bit */ -#define R_ARM_ABS12 6 /* Direct 12 bit */ -#define R_ARM_THM_ABS5 7 /* Direct & 0x7C (LDR, STR). */ -#define R_ARM_ABS8 8 /* Direct 8 bit */ -#define R_ARM_SBREL32 9 -#define R_ARM_THM_PC22 10 /* PC relative 24 bit (Thumb32 BL). */ -#define R_ARM_THM_PC8 11 /* PC relative & 0x3FC - (Thumb16 LDR, ADD, ADR). */ -#define R_ARM_AMP_VCALL9 12 -#define R_ARM_SWI24 13 /* Obsolete static relocation. */ -#define R_ARM_TLS_DESC 13 /* Dynamic relocation. */ -#define R_ARM_THM_SWI8 14 /* Reserved. */ -#define R_ARM_XPC25 15 /* Reserved. */ -#define R_ARM_THM_XPC22 16 /* Reserved. */ -#define R_ARM_TLS_DTPMOD32 17 /* ID of module containing symbol */ -#define R_ARM_TLS_DTPOFF32 18 /* Offset in TLS block */ -#define R_ARM_TLS_TPOFF32 19 /* Offset in static TLS block */ -#define R_ARM_COPY 20 /* Copy symbol at runtime */ -#define R_ARM_GLOB_DAT 21 /* Create GOT entry */ -#define R_ARM_JUMP_SLOT 22 /* Create PLT entry */ -#define R_ARM_RELATIVE 23 /* Adjust by program base */ -#define R_ARM_GOTOFF 24 /* 32 bit offset to GOT */ -#define R_ARM_GOTPC 25 /* 32 bit PC relative offset to GOT */ -#define R_ARM_GOT32 26 /* 32 bit GOT entry */ -#define R_ARM_PLT32 27 /* Deprecated, 32 bit PLT address. */ -#define R_ARM_CALL 28 /* PC relative 24 bit (BL, BLX). */ -#define R_ARM_JUMP24 29 /* PC relative 24 bit - (B, BL<cond>). */ -#define R_ARM_THM_JUMP24 30 /* PC relative 24 bit (Thumb32 B.W). */ -#define R_ARM_BASE_ABS 31 /* Adjust by program base. */ -#define R_ARM_ALU_PCREL_7_0 32 /* Obsolete. */ -#define R_ARM_ALU_PCREL_15_8 33 /* Obsolete. */ -#define R_ARM_ALU_PCREL_23_15 34 /* Obsolete. */ -#define R_ARM_LDR_SBREL_11_0 35 /* Deprecated, prog. base relative. */ -#define R_ARM_ALU_SBREL_19_12 36 /* Deprecated, prog. base relative. */ -#define R_ARM_ALU_SBREL_27_20 37 /* Deprecated, prog. base relative. */ -#define R_ARM_TARGET1 38 -#define R_ARM_SBREL31 39 /* Program base relative. */ -#define R_ARM_V4BX 40 -#define R_ARM_TARGET2 41 -#define R_ARM_PREL31 42 /* 32 bit PC relative. */ -#define R_ARM_MOVW_ABS_NC 43 /* Direct 16-bit (MOVW). */ -#define R_ARM_MOVT_ABS 44 /* Direct high 16-bit (MOVT). */ -#define R_ARM_MOVW_PREL_NC 45 /* PC relative 16-bit (MOVW). */ -#define R_ARM_MOVT_PREL 46 /* PC relative (MOVT). */ -#define R_ARM_THM_MOVW_ABS_NC 47 /* Direct 16 bit (Thumb32 MOVW). */ -#define R_ARM_THM_MOVT_ABS 48 /* Direct high 16 bit - (Thumb32 MOVT). */ -#define R_ARM_THM_MOVW_PREL_NC 49 /* PC relative 16 bit - (Thumb32 MOVW). */ -#define R_ARM_THM_MOVT_PREL 50 /* PC relative high 16 bit - (Thumb32 MOVT). */ -#define R_ARM_THM_JUMP19 51 /* PC relative 20 bit - (Thumb32 B<cond>.W). */ -#define R_ARM_THM_JUMP6 52 /* PC relative X & 0x7E - (Thumb16 CBZ, CBNZ). */ -#define R_ARM_THM_ALU_PREL_11_0 53 /* PC relative 12 bit - (Thumb32 ADR.W). */ -#define R_ARM_THM_PC12 54 /* PC relative 12 bit - (Thumb32 LDR{D,SB,H,SH}). */ -#define R_ARM_ABS32_NOI 55 /* Direct 32-bit. */ -#define R_ARM_REL32_NOI 56 /* PC relative 32-bit. */ -#define R_ARM_ALU_PC_G0_NC 57 /* PC relative (ADD, SUB). */ -#define R_ARM_ALU_PC_G0 58 /* PC relative (ADD, SUB). */ -#define R_ARM_ALU_PC_G1_NC 59 /* PC relative (ADD, SUB). */ -#define R_ARM_ALU_PC_G1 60 /* PC relative (ADD, SUB). */ -#define R_ARM_ALU_PC_G2 61 /* PC relative (ADD, SUB). */ -#define R_ARM_LDR_PC_G1 62 /* PC relative (LDR,STR,LDRB,STRB). */ -#define R_ARM_LDR_PC_G2 63 /* PC relative (LDR,STR,LDRB,STRB). */ -#define R_ARM_LDRS_PC_G0 64 /* PC relative (STR{D,H}, - LDR{D,SB,H,SH}). */ -#define R_ARM_LDRS_PC_G1 65 /* PC relative (STR{D,H}, - LDR{D,SB,H,SH}). */ -#define R_ARM_LDRS_PC_G2 66 /* PC relative (STR{D,H}, - LDR{D,SB,H,SH}). */ -#define R_ARM_LDC_PC_G0 67 /* PC relative (LDC, STC). */ -#define R_ARM_LDC_PC_G1 68 /* PC relative (LDC, STC). */ -#define R_ARM_LDC_PC_G2 69 /* PC relative (LDC, STC). */ -#define R_ARM_ALU_SB_G0_NC 70 /* Program base relative (ADD,SUB). */ -#define R_ARM_ALU_SB_G0 71 /* Program base relative (ADD,SUB). */ -#define R_ARM_ALU_SB_G1_NC 72 /* Program base relative (ADD,SUB). */ -#define R_ARM_ALU_SB_G1 73 /* Program base relative (ADD,SUB). */ -#define R_ARM_ALU_SB_G2 74 /* Program base relative (ADD,SUB). */ -#define R_ARM_LDR_SB_G0 75 /* Program base relative (LDR, - STR, LDRB, STRB). */ -#define R_ARM_LDR_SB_G1 76 /* Program base relative - (LDR, STR, LDRB, STRB). */ -#define R_ARM_LDR_SB_G2 77 /* Program base relative - (LDR, STR, LDRB, STRB). */ -#define R_ARM_LDRS_SB_G0 78 /* Program base relative - (LDR, STR, LDRB, STRB). */ -#define R_ARM_LDRS_SB_G1 79 /* Program base relative - (LDR, STR, LDRB, STRB). */ -#define R_ARM_LDRS_SB_G2 80 /* Program base relative - (LDR, STR, LDRB, STRB). */ -#define R_ARM_LDC_SB_G0 81 /* Program base relative (LDC,STC). */ -#define R_ARM_LDC_SB_G1 82 /* Program base relative (LDC,STC). */ -#define R_ARM_LDC_SB_G2 83 /* Program base relative (LDC,STC). */ -#define R_ARM_MOVW_BREL_NC 84 /* Program base relative 16 - bit (MOVW). */ -#define R_ARM_MOVT_BREL 85 /* Program base relative high - 16 bit (MOVT). */ -#define R_ARM_MOVW_BREL 86 /* Program base relative 16 - bit (MOVW). */ -#define R_ARM_THM_MOVW_BREL_NC 87 /* Program base relative 16 - bit (Thumb32 MOVW). */ -#define R_ARM_THM_MOVT_BREL 88 /* Program base relative high - 16 bit (Thumb32 MOVT). */ -#define R_ARM_THM_MOVW_BREL 89 /* Program base relative 16 - bit (Thumb32 MOVW). */ -#define R_ARM_TLS_GOTDESC 90 -#define R_ARM_TLS_CALL 91 -#define R_ARM_TLS_DESCSEQ 92 /* TLS relaxation. */ -#define R_ARM_THM_TLS_CALL 93 -#define R_ARM_PLT32_ABS 94 -#define R_ARM_GOT_ABS 95 /* GOT entry. */ -#define R_ARM_GOT_PREL 96 /* PC relative GOT entry. */ -#define R_ARM_GOT_BREL12 97 /* GOT entry relative to GOT - origin (LDR). */ -#define R_ARM_GOTOFF12 98 /* 12 bit, GOT entry relative - to GOT origin (LDR, STR). */ -#define R_ARM_GOTRELAX 99 -#define R_ARM_GNU_VTENTRY 100 -#define R_ARM_GNU_VTINHERIT 101 -#define R_ARM_THM_PC11 102 /* PC relative & 0xFFE (Thumb16 B). */ -#define R_ARM_THM_PC9 103 /* PC relative & 0x1FE - (Thumb16 B/B<cond>). */ -#define R_ARM_TLS_GD32 104 /* PC-rel 32 bit for global dynamic - thread local data */ -#define R_ARM_TLS_LDM32 105 /* PC-rel 32 bit for local dynamic - thread local data */ -#define R_ARM_TLS_LDO32 106 /* 32 bit offset relative to TLS - block */ -#define R_ARM_TLS_IE32 107 /* PC-rel 32 bit for GOT entry of - static TLS block offset */ -#define R_ARM_TLS_LE32 108 /* 32 bit offset relative to static - TLS block */ -#define R_ARM_TLS_LDO12 109 /* 12 bit relative to TLS - block (LDR, STR). */ -#define R_ARM_TLS_LE12 110 /* 12 bit relative to static - TLS block (LDR, STR). */ -#define R_ARM_TLS_IE12GP 111 /* 12 bit GOT entry relative - to GOT origin (LDR). */ -#define R_ARM_ME_TOO 128 /* Obsolete. */ -#define R_ARM_THM_TLS_DESCSEQ 129 -#define R_ARM_THM_TLS_DESCSEQ16 129 -#define R_ARM_THM_TLS_DESCSEQ32 130 -#define R_ARM_THM_GOT_BREL12 131 /* GOT entry relative to GOT - origin, 12 bit (Thumb32 LDR). */ -#define R_ARM_IRELATIVE 160 -#define R_ARM_RXPC25 249 -#define R_ARM_RSBREL32 250 -#define R_ARM_THM_RPC22 251 -#define R_ARM_RREL32 252 -#define R_ARM_RABS22 253 -#define R_ARM_RPC24 254 -#define R_ARM_RBASE 255 -/* Keep this the last entry. */ -#define R_ARM_NUM 256 - -/* IA-64 specific declarations. */ - -/* Processor specific flags for the Ehdr e_flags field. */ -#define EF_IA_64_MASKOS 0x0000000f /* os-specific flags */ -#define EF_IA_64_ABI64 0x00000010 /* 64-bit ABI */ -#define EF_IA_64_ARCH 0xff000000 /* arch. version mask */ - -/* Processor specific values for the Phdr p_type field. */ -#define PT_IA_64_ARCHEXT (PT_LOPROC + 0) /* arch extension bits */ -#define PT_IA_64_UNWIND (PT_LOPROC + 1) /* ia64 unwind bits */ -#define PT_IA_64_HP_OPT_ANOT (PT_LOOS + 0x12) -#define PT_IA_64_HP_HSL_ANOT (PT_LOOS + 0x13) -#define PT_IA_64_HP_STACK (PT_LOOS + 0x14) - -/* Processor specific flags for the Phdr p_flags field. */ -#define PF_IA_64_NORECOV 0x80000000 /* spec insns w/o recovery */ - -/* Processor specific values for the Shdr sh_type field. */ -#define SHT_IA_64_EXT (SHT_LOPROC + 0) /* extension bits */ -#define SHT_IA_64_UNWIND (SHT_LOPROC + 1) /* unwind bits */ - -/* Processor specific flags for the Shdr sh_flags field. */ -#define SHF_IA_64_SHORT 0x10000000 /* section near gp */ -#define SHF_IA_64_NORECOV 0x20000000 /* spec insns w/o recovery */ - -/* Processor specific values for the Dyn d_tag field. */ -#define DT_IA_64_PLT_RESERVE (DT_LOPROC + 0) -#define DT_IA_64_NUM 1 - -/* IA-64 relocations. */ -#define R_IA64_NONE 0x00 /* none */ -#define R_IA64_IMM14 0x21 /* symbol + addend, add imm14 */ -#define R_IA64_IMM22 0x22 /* symbol + addend, add imm22 */ -#define R_IA64_IMM64 0x23 /* symbol + addend, mov imm64 */ -#define R_IA64_DIR32MSB 0x24 /* symbol + addend, data4 MSB */ -#define R_IA64_DIR32LSB 0x25 /* symbol + addend, data4 LSB */ -#define R_IA64_DIR64MSB 0x26 /* symbol + addend, data8 MSB */ -#define R_IA64_DIR64LSB 0x27 /* symbol + addend, data8 LSB */ -#define R_IA64_GPREL22 0x2a /* @gprel(sym + add), add imm22 */ -#define R_IA64_GPREL64I 0x2b /* @gprel(sym + add), mov imm64 */ -#define R_IA64_GPREL32MSB 0x2c /* @gprel(sym + add), data4 MSB */ -#define R_IA64_GPREL32LSB 0x2d /* @gprel(sym + add), data4 LSB */ -#define R_IA64_GPREL64MSB 0x2e /* @gprel(sym + add), data8 MSB */ -#define R_IA64_GPREL64LSB 0x2f /* @gprel(sym + add), data8 LSB */ -#define R_IA64_LTOFF22 0x32 /* @ltoff(sym + add), add imm22 */ -#define R_IA64_LTOFF64I 0x33 /* @ltoff(sym + add), mov imm64 */ -#define R_IA64_PLTOFF22 0x3a /* @pltoff(sym + add), add imm22 */ -#define R_IA64_PLTOFF64I 0x3b /* @pltoff(sym + add), mov imm64 */ -#define R_IA64_PLTOFF64MSB 0x3e /* @pltoff(sym + add), data8 MSB */ -#define R_IA64_PLTOFF64LSB 0x3f /* @pltoff(sym + add), data8 LSB */ -#define R_IA64_FPTR64I 0x43 /* @fptr(sym + add), mov imm64 */ -#define R_IA64_FPTR32MSB 0x44 /* @fptr(sym + add), data4 MSB */ -#define R_IA64_FPTR32LSB 0x45 /* @fptr(sym + add), data4 LSB */ -#define R_IA64_FPTR64MSB 0x46 /* @fptr(sym + add), data8 MSB */ -#define R_IA64_FPTR64LSB 0x47 /* @fptr(sym + add), data8 LSB */ -#define R_IA64_PCREL60B 0x48 /* @pcrel(sym + add), brl */ -#define R_IA64_PCREL21B 0x49 /* @pcrel(sym + add), ptb, call */ -#define R_IA64_PCREL21M 0x4a /* @pcrel(sym + add), chk.s */ -#define R_IA64_PCREL21F 0x4b /* @pcrel(sym + add), fchkf */ -#define R_IA64_PCREL32MSB 0x4c /* @pcrel(sym + add), data4 MSB */ -#define R_IA64_PCREL32LSB 0x4d /* @pcrel(sym + add), data4 LSB */ -#define R_IA64_PCREL64MSB 0x4e /* @pcrel(sym + add), data8 MSB */ -#define R_IA64_PCREL64LSB 0x4f /* @pcrel(sym + add), data8 LSB */ -#define R_IA64_LTOFF_FPTR22 0x52 /* @ltoff(@fptr(s+a)), imm22 */ -#define R_IA64_LTOFF_FPTR64I 0x53 /* @ltoff(@fptr(s+a)), imm64 */ -#define R_IA64_LTOFF_FPTR32MSB 0x54 /* @ltoff(@fptr(s+a)), data4 MSB */ -#define R_IA64_LTOFF_FPTR32LSB 0x55 /* @ltoff(@fptr(s+a)), data4 LSB */ -#define R_IA64_LTOFF_FPTR64MSB 0x56 /* @ltoff(@fptr(s+a)), data8 MSB */ -#define R_IA64_LTOFF_FPTR64LSB 0x57 /* @ltoff(@fptr(s+a)), data8 LSB */ -#define R_IA64_SEGREL32MSB 0x5c /* @segrel(sym + add), data4 MSB */ -#define R_IA64_SEGREL32LSB 0x5d /* @segrel(sym + add), data4 LSB */ -#define R_IA64_SEGREL64MSB 0x5e /* @segrel(sym + add), data8 MSB */ -#define R_IA64_SEGREL64LSB 0x5f /* @segrel(sym + add), data8 LSB */ -#define R_IA64_SECREL32MSB 0x64 /* @secrel(sym + add), data4 MSB */ -#define R_IA64_SECREL32LSB 0x65 /* @secrel(sym + add), data4 LSB */ -#define R_IA64_SECREL64MSB 0x66 /* @secrel(sym + add), data8 MSB */ -#define R_IA64_SECREL64LSB 0x67 /* @secrel(sym + add), data8 LSB */ -#define R_IA64_REL32MSB 0x6c /* data 4 + REL */ -#define R_IA64_REL32LSB 0x6d /* data 4 + REL */ -#define R_IA64_REL64MSB 0x6e /* data 8 + REL */ -#define R_IA64_REL64LSB 0x6f /* data 8 + REL */ -#define R_IA64_LTV32MSB 0x74 /* symbol + addend, data4 MSB */ -#define R_IA64_LTV32LSB 0x75 /* symbol + addend, data4 LSB */ -#define R_IA64_LTV64MSB 0x76 /* symbol + addend, data8 MSB */ -#define R_IA64_LTV64LSB 0x77 /* symbol + addend, data8 LSB */ -#define R_IA64_PCREL21BI 0x79 /* @pcrel(sym + add), 21bit inst */ -#define R_IA64_PCREL22 0x7a /* @pcrel(sym + add), 22bit inst */ -#define R_IA64_PCREL64I 0x7b /* @pcrel(sym + add), 64bit inst */ -#define R_IA64_IPLTMSB 0x80 /* dynamic reloc, imported PLT, MSB */ -#define R_IA64_IPLTLSB 0x81 /* dynamic reloc, imported PLT, LSB */ -#define R_IA64_COPY 0x84 /* copy relocation */ -#define R_IA64_SUB 0x85 /* Addend and symbol difference */ -#define R_IA64_LTOFF22X 0x86 /* LTOFF22, relaxable. */ -#define R_IA64_LDXMOV 0x87 /* Use of LTOFF22X. */ -#define R_IA64_TPREL14 0x91 /* @tprel(sym + add), imm14 */ -#define R_IA64_TPREL22 0x92 /* @tprel(sym + add), imm22 */ -#define R_IA64_TPREL64I 0x93 /* @tprel(sym + add), imm64 */ -#define R_IA64_TPREL64MSB 0x96 /* @tprel(sym + add), data8 MSB */ -#define R_IA64_TPREL64LSB 0x97 /* @tprel(sym + add), data8 LSB */ -#define R_IA64_LTOFF_TPREL22 0x9a /* @ltoff(@tprel(s+a)), imm2 */ -#define R_IA64_DTPMOD64MSB 0xa6 /* @dtpmod(sym + add), data8 MSB */ -#define R_IA64_DTPMOD64LSB 0xa7 /* @dtpmod(sym + add), data8 LSB */ -#define R_IA64_LTOFF_DTPMOD22 0xaa /* @ltoff(@dtpmod(sym + add)), imm22 */ -#define R_IA64_DTPREL14 0xb1 /* @dtprel(sym + add), imm14 */ -#define R_IA64_DTPREL22 0xb2 /* @dtprel(sym + add), imm22 */ -#define R_IA64_DTPREL64I 0xb3 /* @dtprel(sym + add), imm64 */ -#define R_IA64_DTPREL32MSB 0xb4 /* @dtprel(sym + add), data4 MSB */ -#define R_IA64_DTPREL32LSB 0xb5 /* @dtprel(sym + add), data4 LSB */ -#define R_IA64_DTPREL64MSB 0xb6 /* @dtprel(sym + add), data8 MSB */ -#define R_IA64_DTPREL64LSB 0xb7 /* @dtprel(sym + add), data8 LSB */ -#define R_IA64_LTOFF_DTPREL22 0xba /* @ltoff(@dtprel(s+a)), imm22 */ - -/* SH specific declarations */ - -/* Processor specific flags for the ELF header e_flags field. */ -#define EF_SH_MACH_MASK 0x1f -#define EF_SH_UNKNOWN 0x0 -#define EF_SH1 0x1 -#define EF_SH2 0x2 -#define EF_SH3 0x3 -#define EF_SH_DSP 0x4 -#define EF_SH3_DSP 0x5 -#define EF_SH4AL_DSP 0x6 -#define EF_SH3E 0x8 -#define EF_SH4 0x9 -#define EF_SH2E 0xb -#define EF_SH4A 0xc -#define EF_SH2A 0xd -#define EF_SH4_NOFPU 0x10 -#define EF_SH4A_NOFPU 0x11 -#define EF_SH4_NOMMU_NOFPU 0x12 -#define EF_SH2A_NOFPU 0x13 -#define EF_SH3_NOMMU 0x14 -#define EF_SH2A_SH4_NOFPU 0x15 -#define EF_SH2A_SH3_NOFPU 0x16 -#define EF_SH2A_SH4 0x17 -#define EF_SH2A_SH3E 0x18 - -/* SH relocs. */ -#define R_SH_NONE 0 -#define R_SH_DIR32 1 -#define R_SH_REL32 2 -#define R_SH_DIR8WPN 3 -#define R_SH_IND12W 4 -#define R_SH_DIR8WPL 5 -#define R_SH_DIR8WPZ 6 -#define R_SH_DIR8BP 7 -#define R_SH_DIR8W 8 -#define R_SH_DIR8L 9 -#define R_SH_SWITCH16 25 -#define R_SH_SWITCH32 26 -#define R_SH_USES 27 -#define R_SH_COUNT 28 -#define R_SH_ALIGN 29 -#define R_SH_CODE 30 -#define R_SH_DATA 31 -#define R_SH_LABEL 32 -#define R_SH_SWITCH8 33 -#define R_SH_GNU_VTINHERIT 34 -#define R_SH_GNU_VTENTRY 35 -#define R_SH_TLS_GD_32 144 -#define R_SH_TLS_LD_32 145 -#define R_SH_TLS_LDO_32 146 -#define R_SH_TLS_IE_32 147 -#define R_SH_TLS_LE_32 148 -#define R_SH_TLS_DTPMOD32 149 -#define R_SH_TLS_DTPOFF32 150 -#define R_SH_TLS_TPOFF32 151 -#define R_SH_GOT32 160 -#define R_SH_PLT32 161 -#define R_SH_COPY 162 -#define R_SH_GLOB_DAT 163 -#define R_SH_JMP_SLOT 164 -#define R_SH_RELATIVE 165 -#define R_SH_GOTOFF 166 -#define R_SH_GOTPC 167 -/* Keep this the last entry. */ -#define R_SH_NUM 256 - -/* S/390 specific definitions. */ - -/* Valid values for the e_flags field. */ - -#define EF_S390_HIGH_GPRS 0x00000001 /* High GPRs kernel facility needed. */ - -/* Additional s390 relocs */ - -#define R_390_NONE 0 /* No reloc. */ -#define R_390_8 1 /* Direct 8 bit. */ -#define R_390_12 2 /* Direct 12 bit. */ -#define R_390_16 3 /* Direct 16 bit. */ -#define R_390_32 4 /* Direct 32 bit. */ -#define R_390_PC32 5 /* PC relative 32 bit. */ -#define R_390_GOT12 6 /* 12 bit GOT offset. */ -#define R_390_GOT32 7 /* 32 bit GOT offset. */ -#define R_390_PLT32 8 /* 32 bit PC relative PLT address. */ -#define R_390_COPY 9 /* Copy symbol at runtime. */ -#define R_390_GLOB_DAT 10 /* Create GOT entry. */ -#define R_390_JMP_SLOT 11 /* Create PLT entry. */ -#define R_390_RELATIVE 12 /* Adjust by program base. */ -#define R_390_GOTOFF32 13 /* 32 bit offset to GOT. */ -#define R_390_GOTPC 14 /* 32 bit PC relative offset to GOT. */ -#define R_390_GOT16 15 /* 16 bit GOT offset. */ -#define R_390_PC16 16 /* PC relative 16 bit. */ -#define R_390_PC16DBL 17 /* PC relative 16 bit shifted by 1. */ -#define R_390_PLT16DBL 18 /* 16 bit PC rel. PLT shifted by 1. */ -#define R_390_PC32DBL 19 /* PC relative 32 bit shifted by 1. */ -#define R_390_PLT32DBL 20 /* 32 bit PC rel. PLT shifted by 1. */ -#define R_390_GOTPCDBL 21 /* 32 bit PC rel. GOT shifted by 1. */ -#define R_390_64 22 /* Direct 64 bit. */ -#define R_390_PC64 23 /* PC relative 64 bit. */ -#define R_390_GOT64 24 /* 64 bit GOT offset. */ -#define R_390_PLT64 25 /* 64 bit PC relative PLT address. */ -#define R_390_GOTENT 26 /* 32 bit PC rel. to GOT entry >> 1. */ -#define R_390_GOTOFF16 27 /* 16 bit offset to GOT. */ -#define R_390_GOTOFF64 28 /* 64 bit offset to GOT. */ -#define R_390_GOTPLT12 29 /* 12 bit offset to jump slot. */ -#define R_390_GOTPLT16 30 /* 16 bit offset to jump slot. */ -#define R_390_GOTPLT32 31 /* 32 bit offset to jump slot. */ -#define R_390_GOTPLT64 32 /* 64 bit offset to jump slot. */ -#define R_390_GOTPLTENT 33 /* 32 bit rel. offset to jump slot. */ -#define R_390_PLTOFF16 34 /* 16 bit offset from GOT to PLT. */ -#define R_390_PLTOFF32 35 /* 32 bit offset from GOT to PLT. */ -#define R_390_PLTOFF64 36 /* 16 bit offset from GOT to PLT. */ -#define R_390_TLS_LOAD 37 /* Tag for load insn in TLS code. */ -#define R_390_TLS_GDCALL 38 /* Tag for function call in general - dynamic TLS code. */ -#define R_390_TLS_LDCALL 39 /* Tag for function call in local - dynamic TLS code. */ -#define R_390_TLS_GD32 40 /* Direct 32 bit for general dynamic - thread local data. */ -#define R_390_TLS_GD64 41 /* Direct 64 bit for general dynamic - thread local data. */ -#define R_390_TLS_GOTIE12 42 /* 12 bit GOT offset for static TLS - block offset. */ -#define R_390_TLS_GOTIE32 43 /* 32 bit GOT offset for static TLS - block offset. */ -#define R_390_TLS_GOTIE64 44 /* 64 bit GOT offset for static TLS - block offset. */ -#define R_390_TLS_LDM32 45 /* Direct 32 bit for local dynamic - thread local data in LE code. */ -#define R_390_TLS_LDM64 46 /* Direct 64 bit for local dynamic - thread local data in LE code. */ -#define R_390_TLS_IE32 47 /* 32 bit address of GOT entry for - negated static TLS block offset. */ -#define R_390_TLS_IE64 48 /* 64 bit address of GOT entry for - negated static TLS block offset. */ -#define R_390_TLS_IEENT 49 /* 32 bit rel. offset to GOT entry for - negated static TLS block offset. */ -#define R_390_TLS_LE32 50 /* 32 bit negated offset relative to - static TLS block. */ -#define R_390_TLS_LE64 51 /* 64 bit negated offset relative to - static TLS block. */ -#define R_390_TLS_LDO32 52 /* 32 bit offset relative to TLS - block. */ -#define R_390_TLS_LDO64 53 /* 64 bit offset relative to TLS - block. */ -#define R_390_TLS_DTPMOD 54 /* ID of module containing symbol. */ -#define R_390_TLS_DTPOFF 55 /* Offset in TLS block. */ -#define R_390_TLS_TPOFF 56 /* Negated offset in static TLS - block. */ -#define R_390_20 57 /* Direct 20 bit. */ -#define R_390_GOT20 58 /* 20 bit GOT offset. */ -#define R_390_GOTPLT20 59 /* 20 bit offset to jump slot. */ -#define R_390_TLS_GOTIE20 60 /* 20 bit GOT offset for static TLS - block offset. */ -#define R_390_IRELATIVE 61 /* STT_GNU_IFUNC relocation. */ -/* Keep this the last entry. */ -#define R_390_NUM 62 - - -/* CRIS relocations. */ -#define R_CRIS_NONE 0 -#define R_CRIS_8 1 -#define R_CRIS_16 2 -#define R_CRIS_32 3 -#define R_CRIS_8_PCREL 4 -#define R_CRIS_16_PCREL 5 -#define R_CRIS_32_PCREL 6 -#define R_CRIS_GNU_VTINHERIT 7 -#define R_CRIS_GNU_VTENTRY 8 -#define R_CRIS_COPY 9 -#define R_CRIS_GLOB_DAT 10 -#define R_CRIS_JUMP_SLOT 11 -#define R_CRIS_RELATIVE 12 -#define R_CRIS_16_GOT 13 -#define R_CRIS_32_GOT 14 -#define R_CRIS_16_GOTPLT 15 -#define R_CRIS_32_GOTPLT 16 -#define R_CRIS_32_GOTREL 17 -#define R_CRIS_32_PLT_GOTREL 18 -#define R_CRIS_32_PLT_PCREL 19 - -#define R_CRIS_NUM 20 - - -/* AMD x86-64 relocations. */ -#define R_X86_64_NONE 0 /* No reloc */ -#define R_X86_64_64 1 /* Direct 64 bit */ -#define R_X86_64_PC32 2 /* PC relative 32 bit signed */ -#define R_X86_64_GOT32 3 /* 32 bit GOT entry */ -#define R_X86_64_PLT32 4 /* 32 bit PLT address */ -#define R_X86_64_COPY 5 /* Copy symbol at runtime */ -#define R_X86_64_GLOB_DAT 6 /* Create GOT entry */ -#define R_X86_64_JUMP_SLOT 7 /* Create PLT entry */ -#define R_X86_64_RELATIVE 8 /* Adjust by program base */ -#define R_X86_64_GOTPCREL 9 /* 32 bit signed PC relative - offset to GOT */ -#define R_X86_64_32 10 /* Direct 32 bit zero extended */ -#define R_X86_64_32S 11 /* Direct 32 bit sign extended */ -#define R_X86_64_16 12 /* Direct 16 bit zero extended */ -#define R_X86_64_PC16 13 /* 16 bit sign extended pc relative */ -#define R_X86_64_8 14 /* Direct 8 bit sign extended */ -#define R_X86_64_PC8 15 /* 8 bit sign extended pc relative */ -#define R_X86_64_DTPMOD64 16 /* ID of module containing symbol */ -#define R_X86_64_DTPOFF64 17 /* Offset in module's TLS block */ -#define R_X86_64_TPOFF64 18 /* Offset in initial TLS block */ -#define R_X86_64_TLSGD 19 /* 32 bit signed PC relative offset - to two GOT entries for GD symbol */ -#define R_X86_64_TLSLD 20 /* 32 bit signed PC relative offset - to two GOT entries for LD symbol */ -#define R_X86_64_DTPOFF32 21 /* Offset in TLS block */ -#define R_X86_64_GOTTPOFF 22 /* 32 bit signed PC relative offset - to GOT entry for IE symbol */ -#define R_X86_64_TPOFF32 23 /* Offset in initial TLS block */ -#define R_X86_64_PC64 24 /* PC relative 64 bit */ -#define R_X86_64_GOTOFF64 25 /* 64 bit offset to GOT */ -#define R_X86_64_GOTPC32 26 /* 32 bit signed pc relative - offset to GOT */ -#define R_X86_64_GOT64 27 /* 64-bit GOT entry offset */ -#define R_X86_64_GOTPCREL64 28 /* 64-bit PC relative offset - to GOT entry */ -#define R_X86_64_GOTPC64 29 /* 64-bit PC relative offset to GOT */ -#define R_X86_64_GOTPLT64 30 /* like GOT64, says PLT entry needed */ -#define R_X86_64_PLTOFF64 31 /* 64-bit GOT relative offset - to PLT entry */ -#define R_X86_64_SIZE32 32 /* Size of symbol plus 32-bit addend */ -#define R_X86_64_SIZE64 33 /* Size of symbol plus 64-bit addend */ -#define R_X86_64_GOTPC32_TLSDESC 34 /* GOT offset for TLS descriptor. */ -#define R_X86_64_TLSDESC_CALL 35 /* Marker for call through TLS - descriptor. */ -#define R_X86_64_TLSDESC 36 /* TLS descriptor. */ -#define R_X86_64_IRELATIVE 37 /* Adjust indirectly by program base */ -#define R_X86_64_RELATIVE64 38 /* 64-bit adjust by program base */ - /* 39 Reserved was R_X86_64_PC32_BND */ - /* 40 Reserved was R_X86_64_PLT32_BND */ -#define R_X86_64_GOTPCRELX 41 /* Load from 32 bit signed pc relative - offset to GOT entry without REX - prefix, relaxable. */ -#define R_X86_64_REX_GOTPCRELX 42 /* Load from 32 bit signed pc relative - offset to GOT entry with REX prefix, - relaxable. */ -#define R_X86_64_NUM 43 - - -/* AM33 relocations. */ -#define R_MN10300_NONE 0 /* No reloc. */ -#define R_MN10300_32 1 /* Direct 32 bit. */ -#define R_MN10300_16 2 /* Direct 16 bit. */ -#define R_MN10300_8 3 /* Direct 8 bit. */ -#define R_MN10300_PCREL32 4 /* PC-relative 32-bit. */ -#define R_MN10300_PCREL16 5 /* PC-relative 16-bit signed. */ -#define R_MN10300_PCREL8 6 /* PC-relative 8-bit signed. */ -#define R_MN10300_GNU_VTINHERIT 7 /* Ancient C++ vtable garbage... */ -#define R_MN10300_GNU_VTENTRY 8 /* ... collection annotation. */ -#define R_MN10300_24 9 /* Direct 24 bit. */ -#define R_MN10300_GOTPC32 10 /* 32-bit PCrel offset to GOT. */ -#define R_MN10300_GOTPC16 11 /* 16-bit PCrel offset to GOT. */ -#define R_MN10300_GOTOFF32 12 /* 32-bit offset from GOT. */ -#define R_MN10300_GOTOFF24 13 /* 24-bit offset from GOT. */ -#define R_MN10300_GOTOFF16 14 /* 16-bit offset from GOT. */ -#define R_MN10300_PLT32 15 /* 32-bit PCrel to PLT entry. */ -#define R_MN10300_PLT16 16 /* 16-bit PCrel to PLT entry. */ -#define R_MN10300_GOT32 17 /* 32-bit offset to GOT entry. */ -#define R_MN10300_GOT24 18 /* 24-bit offset to GOT entry. */ -#define R_MN10300_GOT16 19 /* 16-bit offset to GOT entry. */ -#define R_MN10300_COPY 20 /* Copy symbol at runtime. */ -#define R_MN10300_GLOB_DAT 21 /* Create GOT entry. */ -#define R_MN10300_JMP_SLOT 22 /* Create PLT entry. */ -#define R_MN10300_RELATIVE 23 /* Adjust by program base. */ -#define R_MN10300_TLS_GD 24 /* 32-bit offset for global dynamic. */ -#define R_MN10300_TLS_LD 25 /* 32-bit offset for local dynamic. */ -#define R_MN10300_TLS_LDO 26 /* Module-relative offset. */ -#define R_MN10300_TLS_GOTIE 27 /* GOT offset for static TLS block - offset. */ -#define R_MN10300_TLS_IE 28 /* GOT address for static TLS block - offset. */ -#define R_MN10300_TLS_LE 29 /* Offset relative to static TLS - block. */ -#define R_MN10300_TLS_DTPMOD 30 /* ID of module containing symbol. */ -#define R_MN10300_TLS_DTPOFF 31 /* Offset in module TLS block. */ -#define R_MN10300_TLS_TPOFF 32 /* Offset in static TLS block. */ -#define R_MN10300_SYM_DIFF 33 /* Adjustment for next reloc as needed - by linker relaxation. */ -#define R_MN10300_ALIGN 34 /* Alignment requirement for linker - relaxation. */ -#define R_MN10300_NUM 35 - - -/* M32R relocs. */ -#define R_M32R_NONE 0 /* No reloc. */ -#define R_M32R_16 1 /* Direct 16 bit. */ -#define R_M32R_32 2 /* Direct 32 bit. */ -#define R_M32R_24 3 /* Direct 24 bit. */ -#define R_M32R_10_PCREL 4 /* PC relative 10 bit shifted. */ -#define R_M32R_18_PCREL 5 /* PC relative 18 bit shifted. */ -#define R_M32R_26_PCREL 6 /* PC relative 26 bit shifted. */ -#define R_M32R_HI16_ULO 7 /* High 16 bit with unsigned low. */ -#define R_M32R_HI16_SLO 8 /* High 16 bit with signed low. */ -#define R_M32R_LO16 9 /* Low 16 bit. */ -#define R_M32R_SDA16 10 /* 16 bit offset in SDA. */ -#define R_M32R_GNU_VTINHERIT 11 -#define R_M32R_GNU_VTENTRY 12 -/* M32R relocs use SHT_RELA. */ -#define R_M32R_16_RELA 33 /* Direct 16 bit. */ -#define R_M32R_32_RELA 34 /* Direct 32 bit. */ -#define R_M32R_24_RELA 35 /* Direct 24 bit. */ -#define R_M32R_10_PCREL_RELA 36 /* PC relative 10 bit shifted. */ -#define R_M32R_18_PCREL_RELA 37 /* PC relative 18 bit shifted. */ -#define R_M32R_26_PCREL_RELA 38 /* PC relative 26 bit shifted. */ -#define R_M32R_HI16_ULO_RELA 39 /* High 16 bit with unsigned low */ -#define R_M32R_HI16_SLO_RELA 40 /* High 16 bit with signed low */ -#define R_M32R_LO16_RELA 41 /* Low 16 bit */ -#define R_M32R_SDA16_RELA 42 /* 16 bit offset in SDA */ -#define R_M32R_RELA_GNU_VTINHERIT 43 -#define R_M32R_RELA_GNU_VTENTRY 44 -#define R_M32R_REL32 45 /* PC relative 32 bit. */ - -#define R_M32R_GOT24 48 /* 24 bit GOT entry */ -#define R_M32R_26_PLTREL 49 /* 26 bit PC relative to PLT shifted */ -#define R_M32R_COPY 50 /* Copy symbol at runtime */ -#define R_M32R_GLOB_DAT 51 /* Create GOT entry */ -#define R_M32R_JMP_SLOT 52 /* Create PLT entry */ -#define R_M32R_RELATIVE 53 /* Adjust by program base */ -#define R_M32R_GOTOFF 54 /* 24 bit offset to GOT */ -#define R_M32R_GOTPC24 55 /* 24 bit PC relative offset to GOT */ -#define R_M32R_GOT16_HI_ULO 56 /* High 16 bit GOT entry with unsigned - low */ -#define R_M32R_GOT16_HI_SLO 57 /* High 16 bit GOT entry with signed - low */ -#define R_M32R_GOT16_LO 58 /* Low 16 bit GOT entry */ -#define R_M32R_GOTPC_HI_ULO 59 /* High 16 bit PC relative offset to - GOT with unsigned low */ -#define R_M32R_GOTPC_HI_SLO 60 /* High 16 bit PC relative offset to - GOT with signed low */ -#define R_M32R_GOTPC_LO 61 /* Low 16 bit PC relative offset to - GOT */ -#define R_M32R_GOTOFF_HI_ULO 62 /* High 16 bit offset to GOT - with unsigned low */ -#define R_M32R_GOTOFF_HI_SLO 63 /* High 16 bit offset to GOT - with signed low */ -#define R_M32R_GOTOFF_LO 64 /* Low 16 bit offset to GOT */ -#define R_M32R_NUM 256 /* Keep this the last entry. */ - -/* MicroBlaze relocations */ -#define R_MICROBLAZE_NONE 0 /* No reloc. */ -#define R_MICROBLAZE_32 1 /* Direct 32 bit. */ -#define R_MICROBLAZE_32_PCREL 2 /* PC relative 32 bit. */ -#define R_MICROBLAZE_64_PCREL 3 /* PC relative 64 bit. */ -#define R_MICROBLAZE_32_PCREL_LO 4 /* Low 16 bits of PCREL32. */ -#define R_MICROBLAZE_64 5 /* Direct 64 bit. */ -#define R_MICROBLAZE_32_LO 6 /* Low 16 bit. */ -#define R_MICROBLAZE_SRO32 7 /* Read-only small data area. */ -#define R_MICROBLAZE_SRW32 8 /* Read-write small data area. */ -#define R_MICROBLAZE_64_NONE 9 /* No reloc. */ -#define R_MICROBLAZE_32_SYM_OP_SYM 10 /* Symbol Op Symbol relocation. */ -#define R_MICROBLAZE_GNU_VTINHERIT 11 /* GNU C++ vtable hierarchy. */ -#define R_MICROBLAZE_GNU_VTENTRY 12 /* GNU C++ vtable member usage. */ -#define R_MICROBLAZE_GOTPC_64 13 /* PC-relative GOT offset. */ -#define R_MICROBLAZE_GOT_64 14 /* GOT entry offset. */ -#define R_MICROBLAZE_PLT_64 15 /* PLT offset (PC-relative). */ -#define R_MICROBLAZE_REL 16 /* Adjust by program base. */ -#define R_MICROBLAZE_JUMP_SLOT 17 /* Create PLT entry. */ -#define R_MICROBLAZE_GLOB_DAT 18 /* Create GOT entry. */ -#define R_MICROBLAZE_GOTOFF_64 19 /* 64 bit offset to GOT. */ -#define R_MICROBLAZE_GOTOFF_32 20 /* 32 bit offset to GOT. */ -#define R_MICROBLAZE_COPY 21 /* Runtime copy. */ -#define R_MICROBLAZE_TLS 22 /* TLS Reloc. */ -#define R_MICROBLAZE_TLSGD 23 /* TLS General Dynamic. */ -#define R_MICROBLAZE_TLSLD 24 /* TLS Local Dynamic. */ -#define R_MICROBLAZE_TLSDTPMOD32 25 /* TLS Module ID. */ -#define R_MICROBLAZE_TLSDTPREL32 26 /* TLS Offset Within TLS Block. */ -#define R_MICROBLAZE_TLSDTPREL64 27 /* TLS Offset Within TLS Block. */ -#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 */ -#define R_TILEPRO_16 2 /* Direct 16 bit */ -#define R_TILEPRO_8 3 /* Direct 8 bit */ -#define R_TILEPRO_32_PCREL 4 /* PC relative 32 bit */ -#define R_TILEPRO_16_PCREL 5 /* PC relative 16 bit */ -#define R_TILEPRO_8_PCREL 6 /* PC relative 8 bit */ -#define R_TILEPRO_LO16 7 /* Low 16 bit */ -#define R_TILEPRO_HI16 8 /* High 16 bit */ -#define R_TILEPRO_HA16 9 /* High 16 bit, adjusted */ -#define R_TILEPRO_COPY 10 /* Copy relocation */ -#define R_TILEPRO_GLOB_DAT 11 /* Create GOT entry */ -#define R_TILEPRO_JMP_SLOT 12 /* Create PLT entry */ -#define R_TILEPRO_RELATIVE 13 /* Adjust by program base */ -#define R_TILEPRO_BROFF_X1 14 /* X1 pipe branch offset */ -#define R_TILEPRO_JOFFLONG_X1 15 /* X1 pipe jump offset */ -#define R_TILEPRO_JOFFLONG_X1_PLT 16 /* X1 pipe jump offset to PLT */ -#define R_TILEPRO_IMM8_X0 17 /* X0 pipe 8-bit */ -#define R_TILEPRO_IMM8_Y0 18 /* Y0 pipe 8-bit */ -#define R_TILEPRO_IMM8_X1 19 /* X1 pipe 8-bit */ -#define R_TILEPRO_IMM8_Y1 20 /* Y1 pipe 8-bit */ -#define R_TILEPRO_MT_IMM15_X1 21 /* X1 pipe mtspr */ -#define R_TILEPRO_MF_IMM15_X1 22 /* X1 pipe mfspr */ -#define R_TILEPRO_IMM16_X0 23 /* X0 pipe 16-bit */ -#define R_TILEPRO_IMM16_X1 24 /* X1 pipe 16-bit */ -#define R_TILEPRO_IMM16_X0_LO 25 /* X0 pipe low 16-bit */ -#define R_TILEPRO_IMM16_X1_LO 26 /* X1 pipe low 16-bit */ -#define R_TILEPRO_IMM16_X0_HI 27 /* X0 pipe high 16-bit */ -#define R_TILEPRO_IMM16_X1_HI 28 /* X1 pipe high 16-bit */ -#define R_TILEPRO_IMM16_X0_HA 29 /* X0 pipe high 16-bit, adjusted */ -#define R_TILEPRO_IMM16_X1_HA 30 /* X1 pipe high 16-bit, adjusted */ -#define R_TILEPRO_IMM16_X0_PCREL 31 /* X0 pipe PC relative 16 bit */ -#define R_TILEPRO_IMM16_X1_PCREL 32 /* X1 pipe PC relative 16 bit */ -#define R_TILEPRO_IMM16_X0_LO_PCREL 33 /* X0 pipe PC relative low 16 bit */ -#define R_TILEPRO_IMM16_X1_LO_PCREL 34 /* X1 pipe PC relative low 16 bit */ -#define R_TILEPRO_IMM16_X0_HI_PCREL 35 /* X0 pipe PC relative high 16 bit */ -#define R_TILEPRO_IMM16_X1_HI_PCREL 36 /* X1 pipe PC relative high 16 bit */ -#define R_TILEPRO_IMM16_X0_HA_PCREL 37 /* X0 pipe PC relative ha() 16 bit */ -#define R_TILEPRO_IMM16_X1_HA_PCREL 38 /* X1 pipe PC relative ha() 16 bit */ -#define R_TILEPRO_IMM16_X0_GOT 39 /* X0 pipe 16-bit GOT offset */ -#define R_TILEPRO_IMM16_X1_GOT 40 /* X1 pipe 16-bit GOT offset */ -#define R_TILEPRO_IMM16_X0_GOT_LO 41 /* X0 pipe low 16-bit GOT offset */ -#define R_TILEPRO_IMM16_X1_GOT_LO 42 /* X1 pipe low 16-bit GOT offset */ -#define R_TILEPRO_IMM16_X0_GOT_HI 43 /* X0 pipe high 16-bit GOT offset */ -#define R_TILEPRO_IMM16_X1_GOT_HI 44 /* X1 pipe high 16-bit GOT offset */ -#define R_TILEPRO_IMM16_X0_GOT_HA 45 /* X0 pipe ha() 16-bit GOT offset */ -#define R_TILEPRO_IMM16_X1_GOT_HA 46 /* X1 pipe ha() 16-bit GOT offset */ -#define R_TILEPRO_MMSTART_X0 47 /* X0 pipe mm "start" */ -#define R_TILEPRO_MMEND_X0 48 /* X0 pipe mm "end" */ -#define R_TILEPRO_MMSTART_X1 49 /* X1 pipe mm "start" */ -#define R_TILEPRO_MMEND_X1 50 /* X1 pipe mm "end" */ -#define R_TILEPRO_SHAMT_X0 51 /* X0 pipe shift amount */ -#define R_TILEPRO_SHAMT_X1 52 /* X1 pipe shift amount */ -#define R_TILEPRO_SHAMT_Y0 53 /* Y0 pipe shift amount */ -#define R_TILEPRO_SHAMT_Y1 54 /* Y1 pipe shift amount */ -#define R_TILEPRO_DEST_IMM8_X1 55 /* X1 pipe destination 8-bit */ -/* Relocs 56-59 are currently not defined. */ -#define R_TILEPRO_TLS_GD_CALL 60 /* "jal" for TLS GD */ -#define R_TILEPRO_IMM8_X0_TLS_GD_ADD 61 /* X0 pipe "addi" for TLS GD */ -#define R_TILEPRO_IMM8_X1_TLS_GD_ADD 62 /* X1 pipe "addi" for TLS GD */ -#define R_TILEPRO_IMM8_Y0_TLS_GD_ADD 63 /* Y0 pipe "addi" for TLS GD */ -#define R_TILEPRO_IMM8_Y1_TLS_GD_ADD 64 /* Y1 pipe "addi" for TLS GD */ -#define R_TILEPRO_TLS_IE_LOAD 65 /* "lw_tls" for TLS IE */ -#define R_TILEPRO_IMM16_X0_TLS_GD 66 /* X0 pipe 16-bit TLS GD offset */ -#define R_TILEPRO_IMM16_X1_TLS_GD 67 /* X1 pipe 16-bit TLS GD offset */ -#define R_TILEPRO_IMM16_X0_TLS_GD_LO 68 /* X0 pipe low 16-bit TLS GD offset */ -#define R_TILEPRO_IMM16_X1_TLS_GD_LO 69 /* X1 pipe low 16-bit TLS GD offset */ -#define R_TILEPRO_IMM16_X0_TLS_GD_HI 70 /* X0 pipe high 16-bit TLS GD offset */ -#define R_TILEPRO_IMM16_X1_TLS_GD_HI 71 /* X1 pipe high 16-bit TLS GD offset */ -#define R_TILEPRO_IMM16_X0_TLS_GD_HA 72 /* X0 pipe ha() 16-bit TLS GD offset */ -#define R_TILEPRO_IMM16_X1_TLS_GD_HA 73 /* X1 pipe ha() 16-bit TLS GD offset */ -#define R_TILEPRO_IMM16_X0_TLS_IE 74 /* X0 pipe 16-bit TLS IE offset */ -#define R_TILEPRO_IMM16_X1_TLS_IE 75 /* X1 pipe 16-bit TLS IE offset */ -#define R_TILEPRO_IMM16_X0_TLS_IE_LO 76 /* X0 pipe low 16-bit TLS IE offset */ -#define R_TILEPRO_IMM16_X1_TLS_IE_LO 77 /* X1 pipe low 16-bit TLS IE offset */ -#define R_TILEPRO_IMM16_X0_TLS_IE_HI 78 /* X0 pipe high 16-bit TLS IE offset */ -#define R_TILEPRO_IMM16_X1_TLS_IE_HI 79 /* X1 pipe high 16-bit TLS IE offset */ -#define R_TILEPRO_IMM16_X0_TLS_IE_HA 80 /* X0 pipe ha() 16-bit TLS IE offset */ -#define R_TILEPRO_IMM16_X1_TLS_IE_HA 81 /* X1 pipe ha() 16-bit TLS IE offset */ -#define R_TILEPRO_TLS_DTPMOD32 82 /* ID of module containing symbol */ -#define R_TILEPRO_TLS_DTPOFF32 83 /* Offset in TLS block */ -#define R_TILEPRO_TLS_TPOFF32 84 /* Offset in static TLS block */ -#define R_TILEPRO_IMM16_X0_TLS_LE 85 /* X0 pipe 16-bit TLS LE offset */ -#define R_TILEPRO_IMM16_X1_TLS_LE 86 /* X1 pipe 16-bit TLS LE offset */ -#define R_TILEPRO_IMM16_X0_TLS_LE_LO 87 /* X0 pipe low 16-bit TLS LE offset */ -#define R_TILEPRO_IMM16_X1_TLS_LE_LO 88 /* X1 pipe low 16-bit TLS LE offset */ -#define R_TILEPRO_IMM16_X0_TLS_LE_HI 89 /* X0 pipe high 16-bit TLS LE offset */ -#define R_TILEPRO_IMM16_X1_TLS_LE_HI 90 /* X1 pipe high 16-bit TLS LE offset */ -#define R_TILEPRO_IMM16_X0_TLS_LE_HA 91 /* X0 pipe ha() 16-bit TLS LE offset */ -#define R_TILEPRO_IMM16_X1_TLS_LE_HA 92 /* X1 pipe ha() 16-bit TLS LE offset */ - -#define R_TILEPRO_GNU_VTINHERIT 128 /* GNU C++ vtable hierarchy */ -#define R_TILEPRO_GNU_VTENTRY 129 /* GNU C++ vtable member usage */ - -#define R_TILEPRO_NUM 130 - - -/* TILE-Gx relocations. */ -#define R_TILEGX_NONE 0 /* No reloc */ -#define R_TILEGX_64 1 /* Direct 64 bit */ -#define R_TILEGX_32 2 /* Direct 32 bit */ -#define R_TILEGX_16 3 /* Direct 16 bit */ -#define R_TILEGX_8 4 /* Direct 8 bit */ -#define R_TILEGX_64_PCREL 5 /* PC relative 64 bit */ -#define R_TILEGX_32_PCREL 6 /* PC relative 32 bit */ -#define R_TILEGX_16_PCREL 7 /* PC relative 16 bit */ -#define R_TILEGX_8_PCREL 8 /* PC relative 8 bit */ -#define R_TILEGX_HW0 9 /* hword 0 16-bit */ -#define R_TILEGX_HW1 10 /* hword 1 16-bit */ -#define R_TILEGX_HW2 11 /* hword 2 16-bit */ -#define R_TILEGX_HW3 12 /* hword 3 16-bit */ -#define R_TILEGX_HW0_LAST 13 /* last hword 0 16-bit */ -#define R_TILEGX_HW1_LAST 14 /* last hword 1 16-bit */ -#define R_TILEGX_HW2_LAST 15 /* last hword 2 16-bit */ -#define R_TILEGX_COPY 16 /* Copy relocation */ -#define R_TILEGX_GLOB_DAT 17 /* Create GOT entry */ -#define R_TILEGX_JMP_SLOT 18 /* Create PLT entry */ -#define R_TILEGX_RELATIVE 19 /* Adjust by program base */ -#define R_TILEGX_BROFF_X1 20 /* X1 pipe branch offset */ -#define R_TILEGX_JUMPOFF_X1 21 /* X1 pipe jump offset */ -#define R_TILEGX_JUMPOFF_X1_PLT 22 /* X1 pipe jump offset to PLT */ -#define R_TILEGX_IMM8_X0 23 /* X0 pipe 8-bit */ -#define R_TILEGX_IMM8_Y0 24 /* Y0 pipe 8-bit */ -#define R_TILEGX_IMM8_X1 25 /* X1 pipe 8-bit */ -#define R_TILEGX_IMM8_Y1 26 /* Y1 pipe 8-bit */ -#define R_TILEGX_DEST_IMM8_X1 27 /* X1 pipe destination 8-bit */ -#define R_TILEGX_MT_IMM14_X1 28 /* X1 pipe mtspr */ -#define R_TILEGX_MF_IMM14_X1 29 /* X1 pipe mfspr */ -#define R_TILEGX_MMSTART_X0 30 /* X0 pipe mm "start" */ -#define R_TILEGX_MMEND_X0 31 /* X0 pipe mm "end" */ -#define R_TILEGX_SHAMT_X0 32 /* X0 pipe shift amount */ -#define R_TILEGX_SHAMT_X1 33 /* X1 pipe shift amount */ -#define R_TILEGX_SHAMT_Y0 34 /* Y0 pipe shift amount */ -#define R_TILEGX_SHAMT_Y1 35 /* Y1 pipe shift amount */ -#define R_TILEGX_IMM16_X0_HW0 36 /* X0 pipe hword 0 */ -#define R_TILEGX_IMM16_X1_HW0 37 /* X1 pipe hword 0 */ -#define R_TILEGX_IMM16_X0_HW1 38 /* X0 pipe hword 1 */ -#define R_TILEGX_IMM16_X1_HW1 39 /* X1 pipe hword 1 */ -#define R_TILEGX_IMM16_X0_HW2 40 /* X0 pipe hword 2 */ -#define R_TILEGX_IMM16_X1_HW2 41 /* X1 pipe hword 2 */ -#define R_TILEGX_IMM16_X0_HW3 42 /* X0 pipe hword 3 */ -#define R_TILEGX_IMM16_X1_HW3 43 /* X1 pipe hword 3 */ -#define R_TILEGX_IMM16_X0_HW0_LAST 44 /* X0 pipe last hword 0 */ -#define R_TILEGX_IMM16_X1_HW0_LAST 45 /* X1 pipe last hword 0 */ -#define R_TILEGX_IMM16_X0_HW1_LAST 46 /* X0 pipe last hword 1 */ -#define R_TILEGX_IMM16_X1_HW1_LAST 47 /* X1 pipe last hword 1 */ -#define R_TILEGX_IMM16_X0_HW2_LAST 48 /* X0 pipe last hword 2 */ -#define R_TILEGX_IMM16_X1_HW2_LAST 49 /* X1 pipe last hword 2 */ -#define R_TILEGX_IMM16_X0_HW0_PCREL 50 /* X0 pipe PC relative hword 0 */ -#define R_TILEGX_IMM16_X1_HW0_PCREL 51 /* X1 pipe PC relative hword 0 */ -#define R_TILEGX_IMM16_X0_HW1_PCREL 52 /* X0 pipe PC relative hword 1 */ -#define R_TILEGX_IMM16_X1_HW1_PCREL 53 /* X1 pipe PC relative hword 1 */ -#define R_TILEGX_IMM16_X0_HW2_PCREL 54 /* X0 pipe PC relative hword 2 */ -#define R_TILEGX_IMM16_X1_HW2_PCREL 55 /* X1 pipe PC relative hword 2 */ -#define R_TILEGX_IMM16_X0_HW3_PCREL 56 /* X0 pipe PC relative hword 3 */ -#define R_TILEGX_IMM16_X1_HW3_PCREL 57 /* X1 pipe PC relative hword 3 */ -#define R_TILEGX_IMM16_X0_HW0_LAST_PCREL 58 /* X0 pipe PC-rel last hword 0 */ -#define R_TILEGX_IMM16_X1_HW0_LAST_PCREL 59 /* X1 pipe PC-rel last hword 0 */ -#define R_TILEGX_IMM16_X0_HW1_LAST_PCREL 60 /* X0 pipe PC-rel last hword 1 */ -#define R_TILEGX_IMM16_X1_HW1_LAST_PCREL 61 /* X1 pipe PC-rel last hword 1 */ -#define R_TILEGX_IMM16_X0_HW2_LAST_PCREL 62 /* X0 pipe PC-rel last hword 2 */ -#define R_TILEGX_IMM16_X1_HW2_LAST_PCREL 63 /* X1 pipe PC-rel last hword 2 */ -#define R_TILEGX_IMM16_X0_HW0_GOT 64 /* X0 pipe hword 0 GOT offset */ -#define R_TILEGX_IMM16_X1_HW0_GOT 65 /* X1 pipe hword 0 GOT offset */ -#define R_TILEGX_IMM16_X0_HW0_PLT_PCREL 66 /* X0 pipe PC-rel PLT hword 0 */ -#define R_TILEGX_IMM16_X1_HW0_PLT_PCREL 67 /* X1 pipe PC-rel PLT hword 0 */ -#define R_TILEGX_IMM16_X0_HW1_PLT_PCREL 68 /* X0 pipe PC-rel PLT hword 1 */ -#define R_TILEGX_IMM16_X1_HW1_PLT_PCREL 69 /* X1 pipe PC-rel PLT hword 1 */ -#define R_TILEGX_IMM16_X0_HW2_PLT_PCREL 70 /* X0 pipe PC-rel PLT hword 2 */ -#define R_TILEGX_IMM16_X1_HW2_PLT_PCREL 71 /* X1 pipe PC-rel PLT hword 2 */ -#define R_TILEGX_IMM16_X0_HW0_LAST_GOT 72 /* X0 pipe last hword 0 GOT offset */ -#define R_TILEGX_IMM16_X1_HW0_LAST_GOT 73 /* X1 pipe last hword 0 GOT offset */ -#define R_TILEGX_IMM16_X0_HW1_LAST_GOT 74 /* X0 pipe last hword 1 GOT offset */ -#define R_TILEGX_IMM16_X1_HW1_LAST_GOT 75 /* X1 pipe last hword 1 GOT offset */ -#define R_TILEGX_IMM16_X0_HW3_PLT_PCREL 76 /* X0 pipe PC-rel PLT hword 3 */ -#define R_TILEGX_IMM16_X1_HW3_PLT_PCREL 77 /* X1 pipe PC-rel PLT hword 3 */ -#define R_TILEGX_IMM16_X0_HW0_TLS_GD 78 /* X0 pipe hword 0 TLS GD offset */ -#define R_TILEGX_IMM16_X1_HW0_TLS_GD 79 /* X1 pipe hword 0 TLS GD offset */ -#define R_TILEGX_IMM16_X0_HW0_TLS_LE 80 /* X0 pipe hword 0 TLS LE offset */ -#define R_TILEGX_IMM16_X1_HW0_TLS_LE 81 /* X1 pipe hword 0 TLS LE offset */ -#define R_TILEGX_IMM16_X0_HW0_LAST_TLS_LE 82 /* X0 pipe last hword 0 LE off */ -#define R_TILEGX_IMM16_X1_HW0_LAST_TLS_LE 83 /* X1 pipe last hword 0 LE off */ -#define R_TILEGX_IMM16_X0_HW1_LAST_TLS_LE 84 /* X0 pipe last hword 1 LE off */ -#define R_TILEGX_IMM16_X1_HW1_LAST_TLS_LE 85 /* X1 pipe last hword 1 LE off */ -#define R_TILEGX_IMM16_X0_HW0_LAST_TLS_GD 86 /* X0 pipe last hword 0 GD off */ -#define R_TILEGX_IMM16_X1_HW0_LAST_TLS_GD 87 /* X1 pipe last hword 0 GD off */ -#define R_TILEGX_IMM16_X0_HW1_LAST_TLS_GD 88 /* X0 pipe last hword 1 GD off */ -#define R_TILEGX_IMM16_X1_HW1_LAST_TLS_GD 89 /* X1 pipe last hword 1 GD off */ -/* Relocs 90-91 are currently not defined. */ -#define R_TILEGX_IMM16_X0_HW0_TLS_IE 92 /* X0 pipe hword 0 TLS IE offset */ -#define R_TILEGX_IMM16_X1_HW0_TLS_IE 93 /* X1 pipe hword 0 TLS IE offset */ -#define R_TILEGX_IMM16_X0_HW0_LAST_PLT_PCREL 94 /* X0 pipe PC-rel PLT last hword 0 */ -#define R_TILEGX_IMM16_X1_HW0_LAST_PLT_PCREL 95 /* X1 pipe PC-rel PLT last hword 0 */ -#define R_TILEGX_IMM16_X0_HW1_LAST_PLT_PCREL 96 /* X0 pipe PC-rel PLT last hword 1 */ -#define R_TILEGX_IMM16_X1_HW1_LAST_PLT_PCREL 97 /* X1 pipe PC-rel PLT last hword 1 */ -#define R_TILEGX_IMM16_X0_HW2_LAST_PLT_PCREL 98 /* X0 pipe PC-rel PLT last hword 2 */ -#define R_TILEGX_IMM16_X1_HW2_LAST_PLT_PCREL 99 /* X1 pipe PC-rel PLT last hword 2 */ -#define R_TILEGX_IMM16_X0_HW0_LAST_TLS_IE 100 /* X0 pipe last hword 0 IE off */ -#define R_TILEGX_IMM16_X1_HW0_LAST_TLS_IE 101 /* X1 pipe last hword 0 IE off */ -#define R_TILEGX_IMM16_X0_HW1_LAST_TLS_IE 102 /* X0 pipe last hword 1 IE off */ -#define R_TILEGX_IMM16_X1_HW1_LAST_TLS_IE 103 /* X1 pipe last hword 1 IE off */ -/* Relocs 104-105 are currently not defined. */ -#define R_TILEGX_TLS_DTPMOD64 106 /* 64-bit ID of symbol's module */ -#define R_TILEGX_TLS_DTPOFF64 107 /* 64-bit offset in TLS block */ -#define R_TILEGX_TLS_TPOFF64 108 /* 64-bit offset in static TLS block */ -#define R_TILEGX_TLS_DTPMOD32 109 /* 32-bit ID of symbol's module */ -#define R_TILEGX_TLS_DTPOFF32 110 /* 32-bit offset in TLS block */ -#define R_TILEGX_TLS_TPOFF32 111 /* 32-bit offset in static TLS block */ -#define R_TILEGX_TLS_GD_CALL 112 /* "jal" for TLS GD */ -#define R_TILEGX_IMM8_X0_TLS_GD_ADD 113 /* X0 pipe "addi" for TLS GD */ -#define R_TILEGX_IMM8_X1_TLS_GD_ADD 114 /* X1 pipe "addi" for TLS GD */ -#define R_TILEGX_IMM8_Y0_TLS_GD_ADD 115 /* Y0 pipe "addi" for TLS GD */ -#define R_TILEGX_IMM8_Y1_TLS_GD_ADD 116 /* Y1 pipe "addi" for TLS GD */ -#define R_TILEGX_TLS_IE_LOAD 117 /* "ld_tls" for TLS IE */ -#define R_TILEGX_IMM8_X0_TLS_ADD 118 /* X0 pipe "addi" for TLS GD/IE */ -#define R_TILEGX_IMM8_X1_TLS_ADD 119 /* X1 pipe "addi" for TLS GD/IE */ -#define R_TILEGX_IMM8_Y0_TLS_ADD 120 /* Y0 pipe "addi" for TLS GD/IE */ -#define R_TILEGX_IMM8_Y1_TLS_ADD 121 /* Y1 pipe "addi" for TLS GD/IE */ - -#define R_TILEGX_GNU_VTINHERIT 128 /* GNU C++ vtable hierarchy */ -#define R_TILEGX_GNU_VTENTRY 129 /* GNU C++ vtable member usage */ - -#define R_TILEGX_NUM 130 - -/* BPF specific declarations. */ - -#define R_BPF_NONE 0 /* No reloc */ -#define R_BPF_MAP_FD 1 /* Map fd to pointer */ - -/* Imagination Meta specific relocations. */ - -#define R_METAG_HIADDR16 0 -#define R_METAG_LOADDR16 1 -#define R_METAG_ADDR32 2 /* 32bit absolute address */ -#define R_METAG_NONE 3 /* No reloc */ -#define R_METAG_RELBRANCH 4 -#define R_METAG_GETSETOFF 5 - -/* Backward compatability */ -#define R_METAG_REG32OP1 6 -#define R_METAG_REG32OP2 7 -#define R_METAG_REG32OP3 8 -#define R_METAG_REG16OP1 9 -#define R_METAG_REG16OP2 10 -#define R_METAG_REG16OP3 11 -#define R_METAG_REG32OP4 12 - -#define R_METAG_HIOG 13 -#define R_METAG_LOOG 14 - -#define R_METAG_REL8 15 -#define R_METAG_REL16 16 - -/* GNU */ -#define R_METAG_GNU_VTINHERIT 30 -#define R_METAG_GNU_VTENTRY 31 - -/* PIC relocations */ -#define R_METAG_HI16_GOTOFF 32 -#define R_METAG_LO16_GOTOFF 33 -#define R_METAG_GETSET_GOTOFF 34 -#define R_METAG_GETSET_GOT 35 -#define R_METAG_HI16_GOTPC 36 -#define R_METAG_LO16_GOTPC 37 -#define R_METAG_HI16_PLT 38 -#define R_METAG_LO16_PLT 39 -#define R_METAG_RELBRANCH_PLT 40 -#define R_METAG_GOTOFF 41 -#define R_METAG_PLT 42 -#define R_METAG_COPY 43 -#define R_METAG_JMP_SLOT 44 -#define R_METAG_RELATIVE 45 -#define R_METAG_GLOB_DAT 46 - -/* TLS relocations */ -#define R_METAG_TLS_GD 47 -#define R_METAG_TLS_LDM 48 -#define R_METAG_TLS_LDO_HI16 49 -#define R_METAG_TLS_LDO_LO16 50 -#define R_METAG_TLS_LDO 51 -#define R_METAG_TLS_IE 52 -#define R_METAG_TLS_IENONPIC 53 -#define R_METAG_TLS_IENONPIC_HI16 54 -#define R_METAG_TLS_IENONPIC_LO16 55 -#define R_METAG_TLS_TPOFF 56 -#define R_METAG_TLS_DTPMOD 57 -#define R_METAG_TLS_DTPOFF 58 -#define R_METAG_TLS_LE 59 -#define R_METAG_TLS_LE_HI16 60 -#define R_METAG_TLS_LE_LO16 61 - -__END_DECLS - -#endif /* elf.h */ diff --git a/elf/enbl-secure.c b/elf/enbl-secure.c deleted file mode 100644 index c0723774d9..0000000000 --- a/elf/enbl-secure.c +++ /dev/null @@ -1,36 +0,0 @@ -/* Define and initialize the `__libc_enable_secure' flag. Generic version. - Copyright (C) 1996-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -/* This file is used in the static libc. For the shared library, - dl-sysdep.c defines and initializes __libc_enable_secure. */ - -#include <unistd.h> -#include <libc-internal.h> - -/* If nonzero __libc_enable_secure is already set. */ -int __libc_enable_secure_decided; -/* Safest assumption, if somehow the initializer isn't run. */ -int __libc_enable_secure = 1; - -void -__libc_init_secure (void) -{ - if (__libc_enable_secure_decided == 0) - __libc_enable_secure = (__geteuid () != __getuid () - || __getegid () != __getgid ()); -} diff --git a/elf/failobj.c b/elf/failobj.c deleted file mode 100644 index 500606382e..0000000000 --- a/elf/failobj.c +++ /dev/null @@ -1,10 +0,0 @@ -/* This function is supposed to not exist. */ -extern int xyzzy (int); - -extern int foo (int); - -int -foo (int a) -{ - return xyzzy (a); -} diff --git a/elf/filter.c b/elf/filter.c deleted file mode 100644 index 46aa15ba16..0000000000 --- a/elf/filter.c +++ /dev/null @@ -1,19 +0,0 @@ -#include <mcheck.h> -#include <stdio.h> -#include <string.h> - -extern const char *foo (void); - -int -main (void) -{ - const char *s; - - mtrace (); - - s = foo (); - - printf ("called `foo' from `%s'\n", s); - - return strcmp (s, "filtmod2.c"); -} diff --git a/elf/filtmod1.c b/elf/filtmod1.c deleted file mode 100644 index 1d9b19481d..0000000000 --- a/elf/filtmod1.c +++ /dev/null @@ -1,7 +0,0 @@ -extern const char *foo (void); - -const char * -foo (void) -{ - return __FILE__; -} diff --git a/elf/filtmod2.c b/elf/filtmod2.c deleted file mode 100644 index 1d9b19481d..0000000000 --- a/elf/filtmod2.c +++ /dev/null @@ -1,7 +0,0 @@ -extern const char *foo (void); - -const char * -foo (void) -{ - return __FILE__; -} diff --git a/elf/firstobj.c b/elf/firstobj.c deleted file mode 100644 index 2e6033eab6..0000000000 --- a/elf/firstobj.c +++ /dev/null @@ -1,10 +0,0 @@ -#include <errno.h> - -extern int foo (void); - -int -foo (void) -{ - errno = 0; - return 0; -} diff --git a/elf/gen-trusted-dirs.awk b/elf/gen-trusted-dirs.awk deleted file mode 100644 index 59f10a4856..0000000000 --- a/elf/gen-trusted-dirs.awk +++ /dev/null @@ -1,37 +0,0 @@ -BEGIN { - FS = " "; -} - -{ - for (i = 1; i <= NF; ++i) { - s[cnt++] = $i"/"; - } -} - -END { - printf ("#define SYSTEM_DIRS \\\n"); - - printf (" \"%s\"", s[0]); - - for (i = 1; i < cnt; ++i) { - printf (" \"\\0\" \"%s\"", s[i]); - } - - printf ("\n\n"); - - printf ("#define SYSTEM_DIRS_LEN \\\n"); - - printf (" %d", length (s[0])); - m = length (s[0]); - - for (i = 1; i < cnt; ++i) { - printf (", %d", length(s[i])); - if (length(s[i]) > m) { - m = length(s[i]); - } - } - - printf ("\n\n"); - - printf ("#define SYSTEM_DIRS_MAX_LEN\t%d\n", m); -} diff --git a/elf/genrtldtbl.awk b/elf/genrtldtbl.awk deleted file mode 100644 index 0e2a374901..0000000000 --- a/elf/genrtldtbl.awk +++ /dev/null @@ -1,29 +0,0 @@ -#!/usr/bin/awk -BEGIN { - FS=":"; - count=0; -} -{ - for (i = 1; i <= NF; ++i) { - gsub (/\/*$/, "", $i); - dir[count++] = $i; - } -} -END { - for (i = 0; i < count; ++i) { - printf ("static struct r_search_path_elem rtld_search_dir%d =\n", i+1); - printf (" { \"%s/\", %d, unknown, 0, nonexisting, NULL, NULL, ", - dir[i], length (dir[i]) + 1); - if (i== 0) - printf ("NULL };\n"); - else - printf ("&rtld_search_dir%d };\n", i); - } - printf ("\nstatic struct r_search_path_elem *rtld_search_dirs[] =\n{\n"); - for (i = 0; i < count; ++i) { - printf (" &rtld_search_dir%d,\n", i + 1); - } - printf (" NULL\n};\n\n"); - printf ("static struct r_search_path_elem *all_dirs = &rtld_search_dir%d;\n", - count); -} diff --git a/elf/get-dynamic-info.h b/elf/get-dynamic-info.h deleted file mode 100644 index 7525c3a5b2..0000000000 --- a/elf/get-dynamic-info.h +++ /dev/null @@ -1,184 +0,0 @@ -/* Read the dynamic section at DYN and fill in INFO with indices DT_*. - Copyright (C) 2012-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -/* This file is included multiple times and therefore lacks a header - file inclusion guard. */ - -#include <assert.h> -#include <libc-diag.h> - -#ifndef RESOLVE_MAP -static -#else -auto -#endif -inline void __attribute__ ((unused, always_inline)) -elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp) -{ - ElfW(Dyn) *dyn = l->l_ld; - ElfW(Dyn) **info; -#if __ELF_NATIVE_CLASS == 32 - typedef Elf32_Word d_tag_utype; -#elif __ELF_NATIVE_CLASS == 64 - typedef Elf64_Xword d_tag_utype; -#endif - -#ifndef RTLD_BOOTSTRAP - if (dyn == NULL) - return; -#endif - - info = l->l_info; - - while (dyn->d_tag != DT_NULL) - { - if ((d_tag_utype) dyn->d_tag < DT_NUM) - info[dyn->d_tag] = dyn; - else if (dyn->d_tag >= DT_LOPROC && - dyn->d_tag < DT_LOPROC + DT_THISPROCNUM) - { - /* 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) - info[DT_EXTRATAGIDX (dyn->d_tag) + DT_NUM + DT_THISPROCNUM - + DT_VERSIONTAGNUM] = dyn; - else if ((d_tag_utype) DT_VALTAGIDX (dyn->d_tag) < DT_VALNUM) - info[DT_VALTAGIDX (dyn->d_tag) + DT_NUM + DT_THISPROCNUM - + DT_VERSIONTAGNUM + DT_EXTRANUM] = dyn; - else if ((d_tag_utype) DT_ADDRTAGIDX (dyn->d_tag) < DT_ADDRNUM) - info[DT_ADDRTAGIDX (dyn->d_tag) + DT_NUM + DT_THISPROCNUM - + DT_VERSIONTAGNUM + DT_EXTRANUM + DT_VALNUM] = dyn; - ++dyn; - } - -#define DL_RO_DYN_TEMP_CNT 8 - -#ifndef DL_RO_DYN_SECTION - /* Don't adjust .dynamic unnecessarily. */ - if (l->l_addr != 0) - { - ElfW(Addr) l_addr = l->l_addr; - int cnt = 0; - -# define ADJUST_DYN_INFO(tag) \ - do \ - if (info[tag] != NULL) \ - { \ - if (temp) \ - { \ - temp[cnt].d_tag = info[tag]->d_tag; \ - temp[cnt].d_un.d_ptr = info[tag]->d_un.d_ptr + l_addr; \ - info[tag] = temp + cnt++; \ - } \ - else \ - info[tag]->d_un.d_ptr += l_addr; \ - } \ - while (0) - - ADJUST_DYN_INFO (DT_HASH); - ADJUST_DYN_INFO (DT_PLTGOT); - ADJUST_DYN_INFO (DT_STRTAB); - ADJUST_DYN_INFO (DT_SYMTAB); -# if ! ELF_MACHINE_NO_RELA - ADJUST_DYN_INFO (DT_RELA); -# endif -# if ! ELF_MACHINE_NO_REL - ADJUST_DYN_INFO (DT_REL); -# endif - ADJUST_DYN_INFO (DT_JMPREL); - ADJUST_DYN_INFO (VERSYMIDX (DT_VERSYM)); - ADJUST_DYN_INFO (DT_ADDRTAGIDX (DT_GNU_HASH) + DT_NUM + DT_THISPROCNUM - + DT_VERSIONTAGNUM + DT_EXTRANUM + DT_VALNUM); -# undef ADJUST_DYN_INFO - assert (cnt <= DL_RO_DYN_TEMP_CNT); - } -#endif - if (info[DT_PLTREL] != NULL) - { -#if ELF_MACHINE_NO_RELA - assert (info[DT_PLTREL]->d_un.d_val == DT_REL); -#elif ELF_MACHINE_NO_REL - assert (info[DT_PLTREL]->d_un.d_val == DT_RELA); -#else - assert (info[DT_PLTREL]->d_un.d_val == DT_REL - || info[DT_PLTREL]->d_un.d_val == DT_RELA); -#endif - } -#if ! ELF_MACHINE_NO_RELA - if (info[DT_RELA] != NULL) - assert (info[DT_RELAENT]->d_un.d_val == sizeof (ElfW(Rela))); -# endif -# if ! ELF_MACHINE_NO_REL - if (info[DT_REL] != NULL) - assert (info[DT_RELENT]->d_un.d_val == sizeof (ElfW(Rel))); -#endif -#ifdef RTLD_BOOTSTRAP - /* Only the bind now flags are allowed. */ - assert (info[VERSYMIDX (DT_FLAGS_1)] == NULL - || (info[VERSYMIDX (DT_FLAGS_1)]->d_un.d_val & ~DF_1_NOW) == 0); - assert (info[DT_FLAGS] == NULL - || (info[DT_FLAGS]->d_un.d_val & ~DF_BIND_NOW) == 0); - /* Flags must not be set for ld.so. */ - assert (info[DT_RUNPATH] == NULL); - assert (info[DT_RPATH] == NULL); -#else - if (info[DT_FLAGS] != NULL) - { - /* Flags are used. Translate to the old form where available. - Since these l_info entries are only tested for NULL pointers it - is ok if they point to the DT_FLAGS entry. */ - l->l_flags = info[DT_FLAGS]->d_un.d_val; - - if (l->l_flags & DF_SYMBOLIC) - info[DT_SYMBOLIC] = info[DT_FLAGS]; - if (l->l_flags & DF_TEXTREL) - info[DT_TEXTREL] = info[DT_FLAGS]; - if (l->l_flags & DF_BIND_NOW) - info[DT_BIND_NOW] = info[DT_FLAGS]; - } - if (info[VERSYMIDX (DT_FLAGS_1)] != NULL) - { - l->l_flags_1 = info[VERSYMIDX (DT_FLAGS_1)]->d_un.d_val; - - /* Only DT_1_SUPPORTED_MASK bits are supported, and we would like - to assert this, but we can't. Users have been setting - unsupported DF_1_* flags for a long time and glibc has ignored - them. Therefore to avoid breaking existing applications the - best we can do is add a warning during debugging with the - intent of notifying the user of the problem. */ - if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_FILES, 0) - && l->l_flags_1 & ~DT_1_SUPPORTED_MASK) - _dl_debug_printf ("\nWARNING: Unsupported flag value(s) of 0x%x in DT_FLAGS_1.\n", - l->l_flags_1 & ~DT_1_SUPPORTED_MASK); - - if (l->l_flags_1 & DF_1_NOW) - info[DT_BIND_NOW] = info[VERSYMIDX (DT_FLAGS_1)]; - } - if (info[DT_RUNPATH] != NULL) - /* If both RUNPATH and RPATH are given, the latter is ignored. */ - info[DT_RPATH] = NULL; -#endif -} diff --git a/elf/global.c b/elf/global.c deleted file mode 100644 index c675858b64..0000000000 --- a/elf/global.c +++ /dev/null @@ -1,7 +0,0 @@ -extern int test (void); - -int -main (void) -{ - return test (); -} diff --git a/elf/globalmod1.c b/elf/globalmod1.c deleted file mode 100644 index 3f80822269..0000000000 --- a/elf/globalmod1.c +++ /dev/null @@ -1,17 +0,0 @@ -#include <dlfcn.h> -#include <stdio.h> - -extern int test (void); - -int -test (void) -{ - (void) dlopen ("reldepmod4.so", RTLD_LAZY | RTLD_GLOBAL); - if (dlsym (RTLD_DEFAULT, "call_me") != NULL) - { - puts ("found \"call_me\""); - return 0; - } - puts ("didn't find \"call_me\""); - return 1; -} diff --git a/elf/ifuncdep1.c b/elf/ifuncdep1.c deleted file mode 100644 index 77d663dcec..0000000000 --- a/elf/ifuncdep1.c +++ /dev/null @@ -1,3 +0,0 @@ -/* Test STT_GNU_IFUNC symbols without -fPIC. */ - -#include "ifuncmod1.c" diff --git a/elf/ifuncdep1pic.c b/elf/ifuncdep1pic.c deleted file mode 100644 index b6381e4868..0000000000 --- a/elf/ifuncdep1pic.c +++ /dev/null @@ -1,3 +0,0 @@ -/* Test STT_GNU_IFUNC symbols with -fPIC. */ - -#include "ifuncmod1.c" diff --git a/elf/ifuncdep2.c b/elf/ifuncdep2.c deleted file mode 100644 index d87d61d5be..0000000000 --- a/elf/ifuncdep2.c +++ /dev/null @@ -1,59 +0,0 @@ -/* Test 3 STT_GNU_IFUNC symbols. */ - -#include "ifunc-sel.h" - -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) -{ - return 1; -} - -static int -minus_one (void) -{ - return -1; -} - -static int -zero (void) -{ - return 0; -} - -void * foo1_ifunc (void) __asm__ ("foo1"); -__asm__(".type foo1, %gnu_indirect_function"); - -void * -inhibit_stack_protector -foo1_ifunc (void) -{ - return ifunc_sel (one, minus_one, zero); -} - -void * foo2_ifunc (void) __asm__ ("foo2"); -__asm__(".type foo2, %gnu_indirect_function"); - -void * -inhibit_stack_protector -foo2_ifunc (void) -{ - return ifunc_sel (minus_one, one, zero); -} - -void * foo3_ifunc (void) __asm__ ("foo3"); -__asm__(".type foo3, %gnu_indirect_function"); - -void * -inhibit_stack_protector -foo3_ifunc (void) -{ - return ifunc_sel (one, zero, minus_one); -} diff --git a/elf/ifuncdep2pic.c b/elf/ifuncdep2pic.c deleted file mode 100644 index a84253dbc4..0000000000 --- a/elf/ifuncdep2pic.c +++ /dev/null @@ -1,3 +0,0 @@ -/* Test STT_GNU_IFUNC symbols with -fPIC. */ - -#include "ifuncdep2.c" diff --git a/elf/ifuncdep5.c b/elf/ifuncdep5.c deleted file mode 100644 index f26234336e..0000000000 --- a/elf/ifuncdep5.c +++ /dev/null @@ -1,3 +0,0 @@ -/* Test STT_GNU_IFUNC symbols without -fPIC. */ - -#include "ifuncmod5.c" diff --git a/elf/ifuncdep5pic.c b/elf/ifuncdep5pic.c deleted file mode 100644 index 3edb3a07c6..0000000000 --- a/elf/ifuncdep5pic.c +++ /dev/null @@ -1,3 +0,0 @@ -/* Test STT_GNU_IFUNC symbols with -fPIC. */ - -#include "ifuncmod5.c" diff --git a/elf/ifuncmain1.c b/elf/ifuncmain1.c deleted file mode 100644 index 747fc02648..0000000000 --- a/elf/ifuncmain1.c +++ /dev/null @@ -1,64 +0,0 @@ -/* Test STT_GNU_IFUNC symbols: - - 1. Direct function call. - 2. Function pointer. - 3. Visibility without override. - */ - -#include <stdlib.h> - -int ret_foo; -int ret_foo_hidden; -int ret_foo_protected; - -extern int foo (void); -extern int foo_protected (void); - -#ifndef FOO_P -typedef int (*foo_p) (void); -#endif - -foo_p foo_ptr = foo; -foo_p foo_procted_ptr = foo_protected; - -extern foo_p get_foo_p (void); -extern foo_p get_foo_hidden_p (void); -extern foo_p get_foo_protected_p (void); - -int -main (void) -{ - foo_p p; - - if (foo_ptr != foo) - abort (); - if (foo () != -1) - abort (); - if ((*foo_ptr) () != -1) - abort (); - - if (foo_procted_ptr != foo_protected) - abort (); - if (foo_protected () != 0) - abort (); - if ((*foo_procted_ptr) () != 0) - abort (); - - p = get_foo_p (); - if (p != foo) - abort (); - if (ret_foo != -1 || (*p) () != ret_foo) - abort (); - - p = get_foo_hidden_p (); - if (ret_foo_hidden != 1 || (*p) () != ret_foo_hidden) - abort (); - - p = get_foo_protected_p (); - if (p != foo_protected) - abort (); - if (ret_foo_protected != 0 || (*p) () != ret_foo_protected) - abort (); - - return 0; -} diff --git a/elf/ifuncmain1pic.c b/elf/ifuncmain1pic.c deleted file mode 100644 index db19dc9678..0000000000 --- a/elf/ifuncmain1pic.c +++ /dev/null @@ -1,3 +0,0 @@ -/* Test STT_GNU_IFUNC symbols with -fPIC. */ - -#include "ifuncmain1.c" diff --git a/elf/ifuncmain1picstatic.c b/elf/ifuncmain1picstatic.c deleted file mode 100644 index c937933029..0000000000 --- a/elf/ifuncmain1picstatic.c +++ /dev/null @@ -1,3 +0,0 @@ -/* Test STT_GNU_IFUNC symbols with -fPIC and -static. */ - -#include "ifuncmain1.c" diff --git a/elf/ifuncmain1pie.c b/elf/ifuncmain1pie.c deleted file mode 100644 index c16ef6dd09..0000000000 --- a/elf/ifuncmain1pie.c +++ /dev/null @@ -1,3 +0,0 @@ -/* Test STT_GNU_IFUNC symbols with PIE. */ - -#include "ifuncmain1.c" diff --git a/elf/ifuncmain1static.c b/elf/ifuncmain1static.c deleted file mode 100644 index fdd1e09024..0000000000 --- a/elf/ifuncmain1static.c +++ /dev/null @@ -1,3 +0,0 @@ -/* Test STT_GNU_IFUNC symbols with -static. */ - -#include "ifuncmain1.c" diff --git a/elf/ifuncmain1staticpic.c b/elf/ifuncmain1staticpic.c deleted file mode 100644 index 39e0cbb4b8..0000000000 --- a/elf/ifuncmain1staticpic.c +++ /dev/null @@ -1,3 +0,0 @@ -/* Test STT_GNU_IFUNC symbols with -fPIC and no DSO. */ - -#include "ifuncmain1.c" diff --git a/elf/ifuncmain1staticpie.c b/elf/ifuncmain1staticpie.c deleted file mode 100644 index 4891114260..0000000000 --- a/elf/ifuncmain1staticpie.c +++ /dev/null @@ -1,3 +0,0 @@ -/* Test STT_GNU_IFUNC symbols with PIE and no DSO. */ - -#include "ifuncmain1.c" diff --git a/elf/ifuncmain1vis.c b/elf/ifuncmain1vis.c deleted file mode 100644 index d35e2f81fc..0000000000 --- a/elf/ifuncmain1vis.c +++ /dev/null @@ -1,87 +0,0 @@ -/* Test STT_GNU_IFUNC symbols: - - 1. Direct function call. - 2. Function pointer. - 3. Visibility with override. - */ - -#include <stdlib.h> - -int ret_foo; -int ret_foo_hidden; -int ret_foo_protected; - -extern int foo (void); -extern int foo_protected (void); - -#ifndef FOO_P -typedef int (*foo_p) (void); -#endif - -foo_p foo_ptr = foo; -foo_p foo_procted_ptr = foo_protected; - -extern foo_p get_foo_p (void); -extern foo_p get_foo_hidden_p (void); -extern foo_p get_foo_protected_p (void); - -int -__attribute__ ((noinline)) -foo (void) -{ - return -30; -} - -int -__attribute__ ((noinline)) -foo_hidden (void) -{ - return -20; -} - -int -__attribute__ ((noinline)) -foo_protected (void) -{ - return -40; -} - -int -main (void) -{ - foo_p p; - - if (foo_ptr != foo) - abort (); - if ((*foo_ptr) () != -30) - abort (); - - if (foo_procted_ptr != foo_protected) - abort (); - if ((*foo_procted_ptr) () != -40) - abort (); - - p = get_foo_p (); - if (p != foo) - abort (); - if (foo () != -30) - abort (); - if (ret_foo != -30 || (*p) () != ret_foo) - abort (); - - p = get_foo_hidden_p (); - if (foo_hidden () != -20) - abort (); - if (ret_foo_hidden != 1 || (*p) () != ret_foo_hidden) - abort (); - - p = get_foo_protected_p (); - if (p == foo_protected) - abort (); - if (foo_protected () != -40) - abort (); - if (ret_foo_protected != 0 || (*p) () != ret_foo_protected) - abort (); - - return 0; -} diff --git a/elf/ifuncmain1vispic.c b/elf/ifuncmain1vispic.c deleted file mode 100644 index f8c104d560..0000000000 --- a/elf/ifuncmain1vispic.c +++ /dev/null @@ -1,3 +0,0 @@ -/* Test STT_GNU_IFUNC symbols with -fPIC. */ - -#include "ifuncmain1vis.c" diff --git a/elf/ifuncmain1vispie.c b/elf/ifuncmain1vispie.c deleted file mode 100644 index ad06d2ba1c..0000000000 --- a/elf/ifuncmain1vispie.c +++ /dev/null @@ -1,3 +0,0 @@ -/* Test STT_GNU_IFUNC symbols with PIE. */ - -#include "ifuncmain1vis.c" diff --git a/elf/ifuncmain2.c b/elf/ifuncmain2.c deleted file mode 100644 index db3ba56a02..0000000000 --- a/elf/ifuncmain2.c +++ /dev/null @@ -1,14 +0,0 @@ -/* Test calling one STT_GNU_IFUNC function with 3 different - STT_GNU_IFUNC definitions. */ - -#include <stdlib.h> - -extern int foo1 (void); - -int -main (void) -{ - if (foo1 () != -1) - abort (); - return 0; -} diff --git a/elf/ifuncmain2pic.c b/elf/ifuncmain2pic.c deleted file mode 100644 index 0006012a96..0000000000 --- a/elf/ifuncmain2pic.c +++ /dev/null @@ -1,3 +0,0 @@ -/* Test STT_GNU_IFUNC symbols with -fPIC. */ - -#include "ifuncmain2.c" diff --git a/elf/ifuncmain2picstatic.c b/elf/ifuncmain2picstatic.c deleted file mode 100644 index 3e89db536d..0000000000 --- a/elf/ifuncmain2picstatic.c +++ /dev/null @@ -1,3 +0,0 @@ -/* Test STT_GNU_IFUNC symbols with -fPIC and -static. */ - -#include "ifuncmain2.c" diff --git a/elf/ifuncmain2static.c b/elf/ifuncmain2static.c deleted file mode 100644 index 6932ae8066..0000000000 --- a/elf/ifuncmain2static.c +++ /dev/null @@ -1,3 +0,0 @@ -/* Test STT_GNU_IFUNC symbols with -static. */ - -#include "ifuncmain2.c" diff --git a/elf/ifuncmain3.c b/elf/ifuncmain3.c deleted file mode 100644 index 1574dd5cbe..0000000000 --- a/elf/ifuncmain3.c +++ /dev/null @@ -1,129 +0,0 @@ -/* Test STT_GNU_IFUNC symbols with dlopen: - - 1. Direct function call. - 2. Function pointer. - 3. Visibility with override. - */ - -#include <dlfcn.h> -#include <stdlib.h> -#include <stdio.h> - -typedef int (*foo_p) (void); - -int -__attribute__ ((noinline)) -foo (void) -{ - return -30; -} - -int -__attribute__ ((noinline)) -foo_hidden (void) -{ - return -20; -} - -int -__attribute__ ((noinline)) -foo_protected (void) -{ - return -40; -} - -int -main (void) -{ - foo_p p; - foo_p (*f) (void); - int *ret; - - void *h = dlopen ("ifuncmod3.so", RTLD_LAZY); - if (h == NULL) - { - printf ("cannot load: %s\n", dlerror ()); - return 1; - } - - p = dlsym (h, "foo"); - if (p == NULL) - { - printf ("symbol not found: %s\n", dlerror ()); - return 1; - } - if ((*p) () != -1) - abort (); - - f = dlsym (h, "get_foo_p"); - if (f == NULL) - { - printf ("symbol not found: %s\n", dlerror ()); - return 1; - } - - ret = dlsym (h, "ret_foo"); - if (ret == NULL) - { - printf ("symbol not found: %s\n", dlerror ()); - return 1; - } - - p = (*f) (); - if (p != foo) - abort (); - if (foo () != -30) - abort (); - if (*ret != -30 || (*p) () != *ret) - abort (); - - f = dlsym (h, "get_foo_hidden_p"); - if (f == NULL) - { - printf ("symbol not found: %s\n", dlerror ()); - return 1; - } - - ret = dlsym (h, "ret_foo_hidden"); - if (ret == NULL) - { - printf ("symbol not found: %s\n", dlerror ()); - return 1; - } - - p = (*f) (); - if (foo_hidden () != -20) - abort (); - if (*ret != 1 || (*p) () != *ret) - abort (); - - f = dlsym (h, "get_foo_protected_p"); - if (f == NULL) - { - printf ("symbol not found: %s\n", dlerror ()); - return 1; - } - - ret = dlsym (h, "ret_foo_protected"); - if (ret == NULL) - { - printf ("symbol not found: %s\n", dlerror ()); - return 1; - } - - p = (*f) (); - if (p == foo_protected) - abort (); - if (foo_protected () != -40) - abort (); - if (*ret != 0 || (*p) () != *ret) - abort (); - - if (dlclose (h) != 0) - { - printf ("cannot close: %s\n", dlerror ()); - return 1; - } - - return 0; -} diff --git a/elf/ifuncmain4.c b/elf/ifuncmain4.c deleted file mode 100644 index e55fee2eb3..0000000000 --- a/elf/ifuncmain4.c +++ /dev/null @@ -1,4 +0,0 @@ -/* Test STT_GNU_IFUNC symbols in a single source file. */ - -#include "ifuncmod1.c" -#include "ifuncmain1.c" diff --git a/elf/ifuncmain4picstatic.c b/elf/ifuncmain4picstatic.c deleted file mode 100644 index 977d7f97fc..0000000000 --- a/elf/ifuncmain4picstatic.c +++ /dev/null @@ -1,3 +0,0 @@ -/* Test STT_GNU_IFUNC symbols with -fPIC and -static. */ - -#include "ifuncmain4.c" diff --git a/elf/ifuncmain4static.c b/elf/ifuncmain4static.c deleted file mode 100644 index c399977013..0000000000 --- a/elf/ifuncmain4static.c +++ /dev/null @@ -1,3 +0,0 @@ -/* Test STT_GNU_IFUNC symbols with -static. */ - -#include "ifuncmain4.c" diff --git a/elf/ifuncmain5.c b/elf/ifuncmain5.c deleted file mode 100644 index f398085cb4..0000000000 --- a/elf/ifuncmain5.c +++ /dev/null @@ -1,38 +0,0 @@ -/* Test STT_GNU_IFUNC symbols with dynamic function pointer only. */ - -#include <stdlib.h> - -extern int foo (void); -extern int foo_protected (void); - -typedef int (*foo_p) (void); - -foo_p -__attribute__ ((noinline)) -get_foo (void) -{ - return foo; -} - -foo_p -__attribute__ ((noinline)) -get_foo_protected (void) -{ - return foo_protected; -} - -int -main (void) -{ - foo_p p; - - p = get_foo (); - if ((*p) () != -1) - abort (); - - p = get_foo_protected (); - if ((*p) () != 0) - abort (); - - return 0; -} diff --git a/elf/ifuncmain5pic.c b/elf/ifuncmain5pic.c deleted file mode 100644 index e9144fbb20..0000000000 --- a/elf/ifuncmain5pic.c +++ /dev/null @@ -1,3 +0,0 @@ -/* Test STT_GNU_IFUNC symbols with -fPIC. */ - -#include "ifuncmain5.c" diff --git a/elf/ifuncmain5picstatic.c b/elf/ifuncmain5picstatic.c deleted file mode 100644 index a0afe905d7..0000000000 --- a/elf/ifuncmain5picstatic.c +++ /dev/null @@ -1,3 +0,0 @@ -/* Test STT_GNU_IFUNC symbols with -fPIC and -static. */ - -#include "ifuncmain5.c" diff --git a/elf/ifuncmain5pie.c b/elf/ifuncmain5pie.c deleted file mode 100644 index 669f31eeda..0000000000 --- a/elf/ifuncmain5pie.c +++ /dev/null @@ -1,3 +0,0 @@ -/* Test STT_GNU_IFUNC symbols with PIE. */ - -#include "ifuncmain5.c" diff --git a/elf/ifuncmain5static.c b/elf/ifuncmain5static.c deleted file mode 100644 index 72504404a5..0000000000 --- a/elf/ifuncmain5static.c +++ /dev/null @@ -1,3 +0,0 @@ -/* Test STT_GNU_IFUNC symbols with -static. */ - -#include "ifuncmain5.c" diff --git a/elf/ifuncmain5staticpic.c b/elf/ifuncmain5staticpic.c deleted file mode 100644 index 9e8bac254f..0000000000 --- a/elf/ifuncmain5staticpic.c +++ /dev/null @@ -1,3 +0,0 @@ -/* Test STT_GNU_IFUNC symbols with -fPIC and no DSO. */ - -#include "ifuncmain5.c" diff --git a/elf/ifuncmain6pie.c b/elf/ifuncmain6pie.c deleted file mode 100644 index 04faeb86ef..0000000000 --- a/elf/ifuncmain6pie.c +++ /dev/null @@ -1,65 +0,0 @@ -/* Test STT_GNU_IFUNC symbols in PIE: - - 1. Direct function call. - 2. Function pointer. - 3. Reference from a shared library. - */ - -#include <stdlib.h> -#include "ifunc-sel.h" - -typedef int (*foo_p) (void); -extern foo_p foo_ptr; - -static int -one (void) -{ - return -30; -} - -void * foo_ifunc (void) __asm__ ("foo"); -__asm__(".type foo, %gnu_indirect_function"); - -void * -inhibit_stack_protector -foo_ifunc (void) -{ - return ifunc_one (one); -} - -extern int foo (void); -extern foo_p get_foo (void); -extern foo_p get_foo_p (void); - -foo_p my_foo_ptr = foo; - -int -main (void) -{ - foo_p p; - - p = get_foo (); - if (p != foo) - abort (); - if ((*p) () != -30) - abort (); - - p = get_foo_p (); - if (p != foo) - abort (); - if ((*p) () != -30) - abort (); - - if (foo_ptr != foo) - abort (); - if (my_foo_ptr != foo) - abort (); - if ((*foo_ptr) () != -30) - abort (); - if ((*my_foo_ptr) () != -30) - abort (); - if (foo () != -30) - abort (); - - return 0; -} diff --git a/elf/ifuncmain7.c b/elf/ifuncmain7.c deleted file mode 100644 index 1e8f7ea38e..0000000000 --- a/elf/ifuncmain7.c +++ /dev/null @@ -1,72 +0,0 @@ -/* Test local STT_GNU_IFUNC symbols: - - 1. Direct function call. - 2. Function pointer. - */ - -#include <stdlib.h> -#include "ifunc-sel.h" - -extern int foo (void); - -static int -one (void) -{ - return -30; -} - -static void * foo_ifunc (void) __asm__ ("foo"); -__asm__(".type foo, %gnu_indirect_function"); - -static void * -__attribute__ ((used)) -inhibit_stack_protector -foo_ifunc (void) -{ - return ifunc_one (one); -} - -typedef int (*foo_p) (void); - -foo_p foo_ptr = foo; - -foo_p -__attribute__ ((noinline)) -get_foo_p (void) -{ - return foo_ptr; -} - -foo_p -__attribute__ ((noinline)) -get_foo (void) -{ - return foo; -} - -int -main (void) -{ - foo_p p; - - p = get_foo (); - if (p != foo) - abort (); - if ((*p) () != -30) - abort (); - - p = get_foo_p (); - if (p != foo) - abort (); - if ((*p) () != -30) - abort (); - - if (foo_ptr != foo) - abort (); - if ((*foo_ptr) () != -30) - abort (); - if (foo () != -30) - abort (); - - return 0; -} diff --git a/elf/ifuncmain7pic.c b/elf/ifuncmain7pic.c deleted file mode 100644 index fc37bf4469..0000000000 --- a/elf/ifuncmain7pic.c +++ /dev/null @@ -1,7 +0,0 @@ -/* Test local STT_GNU_IFUNC symbols with -fPIC: - - 1. Direct function call. - 2. Function pointer. - */ - -#include "ifuncmain7.c" diff --git a/elf/ifuncmain7picstatic.c b/elf/ifuncmain7picstatic.c deleted file mode 100644 index baf8934b95..0000000000 --- a/elf/ifuncmain7picstatic.c +++ /dev/null @@ -1,7 +0,0 @@ -/* Test local STT_GNU_IFUNC symbols with -fPIC and -static: - - 1. Direct function call. - 2. Function pointer. - */ - -#include "ifuncmain7.c" diff --git a/elf/ifuncmain7pie.c b/elf/ifuncmain7pie.c deleted file mode 100644 index 254d453f1e..0000000000 --- a/elf/ifuncmain7pie.c +++ /dev/null @@ -1,7 +0,0 @@ -/* Test local STT_GNU_IFUNC symbols with PIE: - - 1. Direct function call. - 2. Function pointer. - */ - -#include "ifuncmain7.c" diff --git a/elf/ifuncmain7static.c b/elf/ifuncmain7static.c deleted file mode 100644 index e470d570ef..0000000000 --- a/elf/ifuncmain7static.c +++ /dev/null @@ -1,7 +0,0 @@ -/* Test local STT_GNU_IFUNC symbols with -static: - - 1. Direct function call. - 2. Function pointer. - */ - -#include "ifuncmain7.c" diff --git a/elf/ifuncmod1.c b/elf/ifuncmod1.c deleted file mode 100644 index f0bf5fb45f..0000000000 --- a/elf/ifuncmod1.c +++ /dev/null @@ -1,100 +0,0 @@ -/* Test STT_GNU_IFUNC symbols: - - 1. Direct function call. - 2. Function pointer. - 3. Visibility. - */ -#include "ifunc-sel.h" - -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) -{ - return 1; -} - -static int -minus_one (void) -{ - return -1; -} - -static int -zero (void) -{ - return 0; -} - -void * foo_ifunc (void) __asm__ ("foo"); -__asm__(".type foo, %gnu_indirect_function"); - -void * -inhibit_stack_protector -foo_ifunc (void) -{ - return ifunc_sel (one, minus_one, zero); -} - -void * foo_hidden_ifunc (void) __asm__ ("foo_hidden"); -__asm__(".type foo_hidden, %gnu_indirect_function"); - -void * -inhibit_stack_protector -foo_hidden_ifunc (void) -{ - return ifunc_sel (minus_one, one, zero); -} - -void * foo_protected_ifunc (void) __asm__ ("foo_protected"); -__asm__(".type foo_protected, %gnu_indirect_function"); - -void * -inhibit_stack_protector -foo_protected_ifunc (void) -{ - return ifunc_sel (one, zero, minus_one); -} - -/* Test hidden indirect function. */ -__asm__(".hidden foo_hidden"); - -/* Test protected indirect function. */ -__asm__(".protected foo_protected"); - -extern int foo (void); -extern int foo_hidden (void); -extern int foo_protected (void); -extern int ret_foo; -extern int ret_foo_hidden; -extern int ret_foo_protected; - -#define FOO_P -typedef int (*foo_p) (void); - -foo_p -get_foo_p (void) -{ - ret_foo = foo (); - return foo; -} - -foo_p -get_foo_hidden_p (void) -{ - ret_foo_hidden = foo_hidden (); - return foo_hidden; -} - -foo_p -get_foo_protected_p (void) -{ - ret_foo_protected = foo_protected (); - return foo_protected; -} diff --git a/elf/ifuncmod3.c b/elf/ifuncmod3.c deleted file mode 100644 index ca2d962600..0000000000 --- a/elf/ifuncmod3.c +++ /dev/null @@ -1,7 +0,0 @@ -/* Test STT_GNU_IFUNC symbols with dlopen. */ - -#include "ifuncmod1.c" - -int ret_foo; -int ret_foo_hidden; -int ret_foo_protected; diff --git a/elf/ifuncmod5.c b/elf/ifuncmod5.c deleted file mode 100644 index 5a957800e8..0000000000 --- a/elf/ifuncmod5.c +++ /dev/null @@ -1,64 +0,0 @@ -/* Test STT_GNU_IFUNC symbols without direct function call. */ -#include "ifunc-sel.h" - -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) -{ - return 1; -} - -static int -minus_one (void) -{ - return -1; -} - -static int -zero (void) -{ - return 0; -} - -void * foo_ifunc (void) __asm__ ("foo"); -__asm__(".type foo, %gnu_indirect_function"); - -void * -inhibit_stack_protector -foo_ifunc (void) -{ - return ifunc_sel (one, minus_one, zero); -} - -void * foo_hidden_ifunc (void) __asm__ ("foo_hidden"); -__asm__(".type foo_hidden, %gnu_indirect_function"); - -void * -inhibit_stack_protector -foo_hidden_ifunc (void) -{ - return ifunc_sel (minus_one, one, zero); -} - -void * foo_protected_ifunc (void) __asm__ ("foo_protected"); -__asm__(".type foo_protected, %gnu_indirect_function"); - -void * -inhibit_stack_protector -foo_protected_ifunc (void) -{ - return ifunc_sel (one, zero, minus_one); -} - -/* Test hidden indirect function. */ -__asm__(".hidden foo_hidden"); - -/* Test protected indirect function. */ -__asm__(".protected foo_protected"); diff --git a/elf/ifuncmod6.c b/elf/ifuncmod6.c deleted file mode 100644 index 2e16c1d06d..0000000000 --- a/elf/ifuncmod6.c +++ /dev/null @@ -1,19 +0,0 @@ -/* Test STT_GNU_IFUNC symbol reference in a shared library. */ - -extern int foo (void); - -typedef int (*foo_p) (void); - -foo_p foo_ptr = foo; - -foo_p -get_foo_p (void) -{ - return foo_ptr; -} - -foo_p -get_foo (void) -{ - return foo; -} diff --git a/elf/initfirst.c b/elf/initfirst.c deleted file mode 100644 index 5ca83d21bc..0000000000 --- a/elf/initfirst.c +++ /dev/null @@ -1,22 +0,0 @@ -#include <dlfcn.h> -#include <stdio.h> - -int -main (void) -{ - void *h = dlopen ("firstobj.so", RTLD_LAZY); - void *f; - if (! h) - { - printf ("cannot find firstobj.so: %s\n", dlerror ()); - return 1; - } - f = dlsym (h, "foo"); - if (! f) - { - printf ("cannot find symbol foo: %s\n", dlerror ()); - return 2; - } - ((void (*) (void)) f) (); - return 0; -} diff --git a/elf/interp.c b/elf/interp.c deleted file mode 100644 index b6e8f04444..0000000000 --- a/elf/interp.c +++ /dev/null @@ -1,22 +0,0 @@ -/* interp - add information about dynamic loader to shared library objects. - Copyright (C) 1996-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -#include <runtime-linker.h> - -const char __invoke_dynamic_linker__[] __attribute__ ((section (".interp"))) - = RUNTIME_LINKER; diff --git a/elf/lateglobal.c b/elf/lateglobal.c deleted file mode 100644 index 4a1a7cd085..0000000000 --- a/elf/lateglobal.c +++ /dev/null @@ -1,47 +0,0 @@ -#include <dlfcn.h> -#include <mcheck.h> -#include <stdio.h> -#include <stdlib.h> - -int -main (void) -{ - void *h[2]; - int fail; - int (*fp) (void); - - mtrace (); - - h[0] = dlopen ("ltglobmod1.so", RTLD_LAZY); - if (h[0] == NULL) - { - printf ("%s: cannot open %s: %s", - __FUNCTION__, "ltglobmod1.so", dlerror ()); - exit (EXIT_FAILURE); - } - h[1] = dlopen ("ltglobmod2.so", RTLD_LAZY); - if (h[1] == NULL) - { - printf ("%s: cannot open %s: %s", - __FUNCTION__, "ltglobmod2.so", dlerror ()); - exit (EXIT_FAILURE); - } - - puts ("loaded \"ltglobmod1.so\" without RTLD_GLOBAL"); - - fp = dlsym (h[1], "foo"); - if (fp == NULL) - { - printf ("cannot get address of `foo': %s", dlerror ()); - exit (EXIT_FAILURE); - } - - fail = fp (); - - puts ("back in main"); - - dlclose (h[1]); - dlclose (h[0]); - - return fail; -} diff --git a/elf/ldconfig.c b/elf/ldconfig.c deleted file mode 100644 index 99caf9e9bb..0000000000 --- a/elf/ldconfig.c +++ /dev/null @@ -1,1418 +0,0 @@ -/* Copyright (C) 1999-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Andreas Jaeger <aj@suse.de>, 1999. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, see <http://www.gnu.org/licenses/>. */ - -#define PROCINFO_CLASS static -#include <alloca.h> -#include <argp.h> -#include <dirent.h> -#include <elf.h> -#include <error.h> -#include <errno.h> -#include <inttypes.h> -#include <libintl.h> -#include <locale.h> -#include <stdbool.h> -#include <stdio.h> -#include <stdio_ext.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <stdint.h> -#include <sys/fcntl.h> -#include <sys/mman.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <glob.h> -#include <libgen.h> - -#include <ldconfig.h> -#include <dl-cache.h> - -#include <dl-procinfo.h> - -#ifdef _DL_FIRST_PLATFORM -# define _DL_FIRST_EXTRA (_DL_FIRST_PLATFORM + _DL_PLATFORMS_COUNT) -#else -# define _DL_FIRST_EXTRA _DL_HWCAP_COUNT -#endif - -#ifndef LD_SO_CONF -# define LD_SO_CONF SYSCONFDIR "/ld.so.conf" -#endif - -/* Get libc version number. */ -#include <version.h> - -#define PACKAGE _libc_intl_domainname - -static const struct -{ - const char *name; - int flag; -} lib_types[] = -{ - {"libc4", FLAG_LIBC4}, - {"libc5", FLAG_ELF_LIBC5}, - {"libc6", FLAG_ELF_LIBC6}, - {"glibc2", FLAG_ELF_LIBC6} -}; - - -/* List of directories to handle. */ -struct dir_entry -{ - char *path; - int flag; - ino64_t ino; - dev_t dev; - struct dir_entry *next; -}; - -/* The list is unsorted, contains no duplicates. Entries are added at - the end. */ -static struct dir_entry *dir_entries; - -/* Flags for different options. */ -/* Print Cache. */ -static int opt_print_cache; - -/* Be verbose. */ -int opt_verbose; - -/* Format to support. */ -/* 0: only libc5/glibc2; 1: both; 2: only glibc 2.2. */ -int opt_format = 1; - -/* Build cache. */ -static int opt_build_cache = 1; - -/* Enable symbolic link processing. If set, create or update symbolic - links, and remove stale symbolic links. */ -static int opt_link = 1; - -/* Only process directories specified on the command line. */ -static int opt_only_cline; - -/* Path to root for chroot. */ -static char *opt_chroot; - -/* Manually link given shared libraries. */ -static int opt_manual_link; - -/* Should we ignore an old auxiliary cache file? */ -static int opt_ignore_aux_cache; - -/* Cache file to use. */ -static char *cache_file; - -/* Configuration file. */ -static const char *config_file; - -/* Mask to use for important hardware capabilities. */ -static unsigned long int hwcap_mask = HWCAP_IMPORTANT; - -/* Configuration-defined capabilities defined in kernel vDSOs. */ -static const char *hwcap_extra[64 - _DL_FIRST_EXTRA]; - -/* Name and version of program. */ -static void print_version (FILE *stream, struct argp_state *state); -void (*argp_program_version_hook) (FILE *, struct argp_state *) - = print_version; - -/* Function to print some extra text in the help message. */ -static char *more_help (int key, const char *text, void *input); - -/* Definitions of arguments for argp functions. */ -static const struct argp_option options[] = -{ - { "print-cache", 'p', NULL, 0, N_("Print cache"), 0}, - { "verbose", 'v', NULL, 0, N_("Generate verbose messages"), 0}, - { NULL, 'N', NULL, 0, N_("Don't build cache"), 0}, - { NULL, 'X', NULL, 0, N_("Don't update symbolic links"), 0}, - { NULL, 'r', N_("ROOT"), 0, N_("Change to and use ROOT as root directory"), 0}, - { NULL, 'C', N_("CACHE"), 0, N_("Use CACHE as cache file"), 0}, - { NULL, 'f', N_("CONF"), 0, N_("Use CONF as configuration file"), 0}, - { NULL, 'n', NULL, 0, N_("Only process directories specified on the command line. Don't build cache."), 0}, - { NULL, 'l', NULL, 0, N_("Manually link individual libraries."), 0}, - { "format", 'c', N_("FORMAT"), 0, N_("Format to use: new, old or compat (default)"), 0}, - { "ignore-aux-cache", 'i', NULL, 0, N_("Ignore auxiliary cache file"), 0}, - { NULL, 0, NULL, 0, NULL, 0 } -}; - -#define PROCINFO_CLASS static -#include <dl-procinfo.c> - -/* Short description of program. */ -static const char doc[] = N_("Configure Dynamic Linker Run Time Bindings."); - -/* Prototype for option handler. */ -static error_t parse_opt (int key, char *arg, struct argp_state *state); - -/* Data structure to communicate with argp functions. */ -static struct argp argp = -{ - options, parse_opt, NULL, doc, NULL, more_help, NULL -}; - -/* Check if string corresponds to an important hardware capability or - a platform. */ -static int -is_hwcap_platform (const char *name) -{ - int hwcap_idx = _dl_string_hwcap (name); - - /* Is this a normal hwcap for the machine like "fpu?" */ - if (hwcap_idx != -1 && ((1 << hwcap_idx) & hwcap_mask)) - return 1; - - /* Is this a platform pseudo-hwcap like "i686?" */ - hwcap_idx = _dl_string_platform (name); - if (hwcap_idx != -1) - return 1; - - /* Is this one of the extra pseudo-hwcaps that we map beyond - _DL_FIRST_EXTRA like "tls", or "nosegneg?" */ - for (hwcap_idx = _DL_FIRST_EXTRA; hwcap_idx < 64; ++hwcap_idx) - if (hwcap_extra[hwcap_idx - _DL_FIRST_EXTRA] != NULL - && !strcmp (name, hwcap_extra[hwcap_idx - _DL_FIRST_EXTRA])) - return 1; - - return 0; -} - -/* Get hwcap (including platform) encoding of path. */ -static uint64_t -path_hwcap (const char *path) -{ - char *str = xstrdup (path); - char *ptr; - uint64_t hwcap = 0; - uint64_t h; - - size_t len; - - len = strlen (str); - if (str[len] == '/') - str[len] = '\0'; - - /* Search pathname from the end and check for hwcap strings. */ - for (;;) - { - ptr = strrchr (str, '/'); - - if (ptr == NULL) - break; - - h = _dl_string_hwcap (ptr + 1); - - if (h == (uint64_t) -1) - { - h = _dl_string_platform (ptr + 1); - if (h == (uint64_t) -1) - { - for (h = _DL_FIRST_EXTRA; h < 64; ++h) - if (hwcap_extra[h - _DL_FIRST_EXTRA] != NULL - && !strcmp (ptr + 1, hwcap_extra[h - _DL_FIRST_EXTRA])) - break; - if (h == 64) - break; - } - } - hwcap += 1ULL << h; - - /* Search the next part of the path. */ - *ptr = '\0'; - } - - free (str); - return hwcap; -} - -/* Handle program arguments. */ -static error_t -parse_opt (int key, char *arg, struct argp_state *state) -{ - switch (key) - { - case 'C': - cache_file = arg; - /* Ignore auxiliary cache since we use non-standard cache. */ - opt_ignore_aux_cache = 1; - break; - case 'f': - config_file = arg; - break; - case 'i': - opt_ignore_aux_cache = 1; - break; - case 'l': - opt_manual_link = 1; - break; - case 'N': - opt_build_cache = 0; - break; - case 'n': - opt_build_cache = 0; - opt_only_cline = 1; - break; - case 'p': - opt_print_cache = 1; - break; - case 'r': - opt_chroot = arg; - break; - case 'v': - opt_verbose = 1; - break; - case 'X': - opt_link = 0; - break; - case 'c': - if (strcmp (arg, "old") == 0) - opt_format = 0; - else if (strcmp (arg, "compat") == 0) - opt_format = 1; - else if (strcmp (arg, "new") == 0) - opt_format = 2; - break; - default: - return ARGP_ERR_UNKNOWN; - } - - return 0; -} - -/* Print bug-reporting information in the help message. */ -static char * -more_help (int key, const char *text, void *input) -{ - char *tp = NULL; - switch (key) - { - case ARGP_KEY_HELP_EXTRA: - /* We print some extra information. */ - if (asprintf (&tp, gettext ("\ -For bug reporting instructions, please see:\n\ -%s.\n"), REPORT_BUGS_TO) < 0) - return NULL; - return tp; - default: - break; - } - return (char *) text; -} - -/* Print the version information. */ -static void -print_version (FILE *stream, struct argp_state *state) -{ - fprintf (stream, "ldconfig %s%s\n", PKGVERSION, VERSION); - fprintf (stream, gettext ("\ -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\ -"), "2017"); - fprintf (stream, gettext ("Written by %s.\n"), - "Andreas Jaeger"); -} - -/* Add a single directory entry. */ -static void -add_single_dir (struct dir_entry *entry, int verbose) -{ - struct dir_entry *ptr, *prev; - - ptr = dir_entries; - prev = ptr; - while (ptr != NULL) - { - /* Check for duplicates. */ - if (ptr->ino == entry->ino && ptr->dev == entry->dev) - { - if (opt_verbose && verbose) - error (0, 0, _("Path `%s' given more than once"), entry->path); - /* Use the newer information. */ - ptr->flag = entry->flag; - free (entry->path); - free (entry); - break; - } - prev = ptr; - ptr = ptr->next; - } - /* Is this the first entry? */ - if (ptr == NULL && dir_entries == NULL) - dir_entries = entry; - else if (ptr == NULL) - prev->next = entry; -} - -/* Add one directory to the list of directories to process. */ -static void -add_dir (const char *line) -{ - unsigned int i; - struct dir_entry *entry = xmalloc (sizeof (struct dir_entry)); - entry->next = NULL; - - /* Search for an '=' sign. */ - entry->path = xstrdup (line); - char *equal_sign = strchr (entry->path, '='); - if (equal_sign) - { - *equal_sign = '\0'; - ++equal_sign; - entry->flag = FLAG_ANY; - for (i = 0; i < sizeof (lib_types) / sizeof (lib_types[0]); ++i) - if (strcmp (equal_sign, lib_types[i].name) == 0) - { - entry->flag = lib_types[i].flag; - break; - } - if (entry->flag == FLAG_ANY) - error (0, 0, _("%s is not a known library type"), equal_sign); - } - else - { - entry->flag = FLAG_ANY; - } - - /* Canonify path: for now only remove leading and trailing - whitespace and the trailing slashes. */ - i = strlen (entry->path); - - while (i > 0 && isspace (entry->path[i - 1])) - entry->path[--i] = '\0'; - - while (i > 0 && entry->path[i - 1] == '/') - entry->path[--i] = '\0'; - - if (i == 0) - return; - - char *path = entry->path; - if (opt_chroot) - path = chroot_canon (opt_chroot, path); - - struct stat64 stat_buf; - if (path == NULL || stat64 (path, &stat_buf)) - { - if (opt_verbose) - error (0, errno, _("Can't stat %s"), entry->path); - free (entry->path); - free (entry); - } - else - { - entry->ino = stat_buf.st_ino; - entry->dev = stat_buf.st_dev; - - add_single_dir (entry, 1); - } - - if (opt_chroot) - free (path); -} - - -static int -chroot_stat (const char *real_path, const char *path, struct stat64 *st) -{ - int ret; - char *canon_path; - - if (!opt_chroot) - return stat64 (real_path, st); - - ret = lstat64 (real_path, st); - if (ret || !S_ISLNK (st->st_mode)) - return ret; - - canon_path = chroot_canon (opt_chroot, path); - if (canon_path == NULL) - return -1; - - ret = stat64 (canon_path, st); - free (canon_path); - return ret; -} - -/* Create a symbolic link from soname to libname in directory path. */ -static void -create_links (const char *real_path, const char *path, const char *libname, - const char *soname) -{ - char *full_libname, *full_soname; - char *real_full_libname, *real_full_soname; - struct stat64 stat_lib, stat_so, lstat_so; - int do_link = 1; - int do_remove = 1; - /* XXX: The logics in this function should be simplified. */ - - /* Get complete path. */ - full_libname = alloca (strlen (path) + strlen (libname) + 2); - full_soname = alloca (strlen (path) + strlen (soname) + 2); - sprintf (full_libname, "%s/%s", path, libname); - sprintf (full_soname, "%s/%s", path, soname); - if (opt_chroot) - { - real_full_libname = alloca (strlen (real_path) + strlen (libname) + 2); - real_full_soname = alloca (strlen (real_path) + strlen (soname) + 2); - sprintf (real_full_libname, "%s/%s", real_path, libname); - sprintf (real_full_soname, "%s/%s", real_path, soname); - } - else - { - real_full_libname = full_libname; - real_full_soname = full_soname; - } - - /* Does soname already exist and point to the right library? */ - if (chroot_stat (real_full_soname, full_soname, &stat_so) == 0) - { - if (chroot_stat (real_full_libname, full_libname, &stat_lib)) - { - error (0, 0, _("Can't stat %s\n"), full_libname); - return; - } - if (stat_lib.st_dev == stat_so.st_dev - && stat_lib.st_ino == stat_so.st_ino) - /* Link is already correct. */ - do_link = 0; - else if (lstat64 (full_soname, &lstat_so) == 0 - && !S_ISLNK (lstat_so.st_mode)) - { - error (0, 0, _("%s is not a symbolic link\n"), full_soname); - do_link = 0; - do_remove = 0; - } - } - else if (lstat64 (real_full_soname, &lstat_so) != 0 - || !S_ISLNK (lstat_so.st_mode)) - /* Unless it is a stale symlink, there is no need to remove. */ - do_remove = 0; - - if (opt_verbose) - printf ("\t%s -> %s", soname, libname); - - if (do_link && opt_link) - { - /* Remove old link. */ - if (do_remove) - if (unlink (real_full_soname)) - { - error (0, 0, _("Can't unlink %s"), full_soname); - do_link = 0; - } - /* Create symbolic link. */ - if (do_link && symlink (libname, real_full_soname)) - { - error (0, 0, _("Can't link %s to %s"), full_soname, libname); - do_link = 0; - } - if (opt_verbose) - { - if (do_link) - fputs (_(" (changed)\n"), stdout); - else - fputs (_(" (SKIPPED)\n"), stdout); - } - } - else if (opt_verbose) - fputs ("\n", stdout); -} - -/* Manually link the given library. */ -static void -manual_link (char *library) -{ - char *path; - char *real_path; - char *real_library; - char *libname; - char *soname; - struct stat64 stat_buf; - int flag; - unsigned int osversion; - - /* Prepare arguments for create_links call. Split library name in - directory and filename first. Since path is allocated, we've got - to be careful to free at the end. */ - path = xstrdup (library); - libname = strrchr (path, '/'); - - if (libname) - { - /* Successfully split names. Check if path is just "/" to avoid - an empty path. */ - if (libname == path) - { - libname = library + 1; - path = xrealloc (path, 2); - strcpy (path, "/"); - } - else - { - *libname = '\0'; - ++libname; - } - } - else - { - /* There's no path, construct one. */ - libname = library; - path = xrealloc (path, 2); - strcpy (path, "."); - } - - if (opt_chroot) - { - real_path = chroot_canon (opt_chroot, path); - if (real_path == NULL) - { - error (0, errno, _("Can't find %s"), path); - free (path); - return; - } - real_library = alloca (strlen (real_path) + strlen (libname) + 2); - sprintf (real_library, "%s/%s", real_path, libname); - } - else - { - real_path = path; - real_library = library; - } - - /* Do some sanity checks first. */ - if (lstat64 (real_library, &stat_buf)) - { - error (0, errno, _("Cannot lstat %s"), library); - free (path); - return; - } - /* We don't want links here! */ - else if (!S_ISREG (stat_buf.st_mode)) - { - error (0, 0, _("Ignored file %s since it is not a regular file."), - library); - free (path); - return; - } - - if (process_file (real_library, library, libname, &flag, &osversion, - &soname, 0, &stat_buf)) - { - error (0, 0, _("No link created since soname could not be found for %s"), - library); - free (path); - return; - } - if (soname == NULL) - soname = implicit_soname (libname, flag); - create_links (real_path, path, libname, soname); - free (soname); - free (path); -} - - -/* Read a whole directory and search for libraries. - The purpose is two-fold: - - search for libraries which will be added to the cache - - create symbolic links to the soname for each library - - This has to be done separatly for each directory. - - To keep track of which libraries to add to the cache and which - links to create, we save a list of all libraries. - - The algorithm is basically: - for all libraries in the directory do - get soname of library - if soname is already in list - if new library is newer, replace entry - otherwise ignore this library - otherwise add library to list - - For example, if the two libraries libxy.so.1.1 and libxy.so.1.2 - exist and both have the same soname, e.g. libxy.so, a symbolic link - is created from libxy.so.1.2 (the newer one) to libxy.so. - libxy.so.1.2 and libxy.so are added to the cache - but not - libxy.so.1.1. */ - -/* Information for one library. */ -struct dlib_entry -{ - char *name; - char *soname; - int flag; - int is_link; - unsigned int osversion; - struct dlib_entry *next; -}; - - -static void -search_dir (const struct dir_entry *entry) -{ - uint64_t hwcap = path_hwcap (entry->path); - if (opt_verbose) - { - if (hwcap != 0) - printf ("%s: (hwcap: %#.16" PRIx64 ")\n", entry->path, hwcap); - else - printf ("%s:\n", entry->path); - } - - char *dir_name; - char *real_file_name; - size_t real_file_name_len; - size_t file_name_len = PATH_MAX; - char *file_name = alloca (file_name_len); - if (opt_chroot) - { - dir_name = chroot_canon (opt_chroot, entry->path); - real_file_name_len = PATH_MAX; - real_file_name = alloca (real_file_name_len); - } - else - { - dir_name = entry->path; - real_file_name_len = 0; - real_file_name = file_name; - } - - DIR *dir; - if (dir_name == NULL || (dir = opendir (dir_name)) == NULL) - { - if (opt_verbose) - error (0, errno, _("Can't open directory %s"), entry->path); - if (opt_chroot && dir_name) - free (dir_name); - return; - } - - struct dirent64 *direntry; - struct dlib_entry *dlibs = NULL; - while ((direntry = readdir64 (dir)) != NULL) - { - int flag; -#ifdef _DIRENT_HAVE_D_TYPE - /* We only look at links and regular files. */ - if (direntry->d_type != DT_UNKNOWN - && direntry->d_type != DT_LNK - && direntry->d_type != DT_REG - && direntry->d_type != DT_DIR) - continue; -#endif /* _DIRENT_HAVE_D_TYPE */ - /* Does this file look like a shared library or is it a hwcap - subdirectory? The dynamic linker is also considered as - shared library. */ - if (((strncmp (direntry->d_name, "lib", 3) != 0 - && strncmp (direntry->d_name, "ld-", 3) != 0) - || strstr (direntry->d_name, ".so") == NULL) - && ( -#ifdef _DIRENT_HAVE_D_TYPE - direntry->d_type == DT_REG || -#endif - !is_hwcap_platform (direntry->d_name))) - continue; - - size_t len = strlen (direntry->d_name); - /* Skip temporary files created by the prelink program. Files with - names like these are never really DSOs we want to look at. */ - if (len >= sizeof (".#prelink#") - 1) - { - if (strcmp (direntry->d_name + len - sizeof (".#prelink#") + 1, - ".#prelink#") == 0) - continue; - if (len >= sizeof (".#prelink#.XXXXXX") - 1 - && memcmp (direntry->d_name + len - sizeof (".#prelink#.XXXXXX") - + 1, ".#prelink#.", sizeof (".#prelink#.") - 1) == 0) - continue; - } - len += strlen (entry->path) + 2; - if (len > file_name_len) - { - file_name_len = len; - file_name = alloca (file_name_len); - if (!opt_chroot) - real_file_name = file_name; - } - sprintf (file_name, "%s/%s", entry->path, direntry->d_name); - if (opt_chroot) - { - len = strlen (dir_name) + strlen (direntry->d_name) + 2; - if (len > real_file_name_len) - { - real_file_name_len = len; - real_file_name = alloca (real_file_name_len); - } - sprintf (real_file_name, "%s/%s", dir_name, direntry->d_name); - } - - struct stat64 lstat_buf; -#ifdef _DIRENT_HAVE_D_TYPE - /* We optimize and try to do the lstat call only if needed. */ - if (direntry->d_type != DT_UNKNOWN) - lstat_buf.st_mode = DTTOIF (direntry->d_type); - else -#endif - if (__glibc_unlikely (lstat64 (real_file_name, &lstat_buf))) - { - error (0, errno, _("Cannot lstat %s"), file_name); - continue; - } - - struct stat64 stat_buf; - int is_dir; - int is_link = S_ISLNK (lstat_buf.st_mode); - if (is_link) - { - /* In case of symlink, we check if the symlink refers to - a directory. */ - char *target_name = real_file_name; - if (opt_chroot) - { - target_name = chroot_canon (opt_chroot, file_name); - if (target_name == NULL) - { - if (strstr (file_name, ".so") == NULL) - error (0, 0, _("Input file %s not found.\n"), file_name); - continue; - } - } - if (__glibc_unlikely (stat64 (target_name, &stat_buf))) - { - if (opt_verbose) - error (0, errno, _("Cannot stat %s"), file_name); - - /* Remove stale symlinks. */ - if (opt_link && strstr (direntry->d_name, ".so.")) - unlink (real_file_name); - continue; - } - is_dir = S_ISDIR (stat_buf.st_mode); - - /* lstat_buf is later stored, update contents. */ - lstat_buf.st_dev = stat_buf.st_dev; - lstat_buf.st_ino = stat_buf.st_ino; - lstat_buf.st_size = stat_buf.st_size; - lstat_buf.st_ctime = stat_buf.st_ctime; - } - else - is_dir = S_ISDIR (lstat_buf.st_mode); - - if (is_dir && is_hwcap_platform (direntry->d_name)) - { - /* Handle subdirectory later. */ - struct dir_entry *new_entry; - - new_entry = xmalloc (sizeof (struct dir_entry)); - new_entry->path = xstrdup (file_name); - new_entry->flag = entry->flag; - new_entry->next = NULL; -#ifdef _DIRENT_HAVE_D_TYPE - /* We have filled in lstat only #ifndef - _DIRENT_HAVE_D_TYPE. Fill it in if needed. */ - if (!is_link - && direntry->d_type != DT_UNKNOWN - && __builtin_expect (lstat64 (real_file_name, &lstat_buf), 0)) - { - error (0, errno, _("Cannot lstat %s"), file_name); - free (new_entry->path); - free (new_entry); - continue; - } -#endif - new_entry->ino = lstat_buf.st_ino; - new_entry->dev = lstat_buf.st_dev; - add_single_dir (new_entry, 0); - continue; - } - else if (!S_ISREG (lstat_buf.st_mode) && !is_link) - continue; - - char *real_name; - if (opt_chroot && is_link) - { - real_name = chroot_canon (opt_chroot, file_name); - if (real_name == NULL) - { - if (strstr (file_name, ".so") == NULL) - error (0, 0, _("Input file %s not found.\n"), file_name); - continue; - } - } - else - real_name = real_file_name; - -#ifdef _DIRENT_HAVE_D_TYPE - /* Call lstat64 if not done yet. */ - if (!is_link - && direntry->d_type != DT_UNKNOWN - && __builtin_expect (lstat64 (real_file_name, &lstat_buf), 0)) - { - error (0, errno, _("Cannot lstat %s"), file_name); - continue; - } -#endif - - /* First search whether the auxiliary cache contains this - library already and it's not changed. */ - char *soname; - unsigned int osversion; - if (!search_aux_cache (&lstat_buf, &flag, &osversion, &soname)) - { - if (process_file (real_name, file_name, direntry->d_name, &flag, - &osversion, &soname, is_link, &lstat_buf)) - { - if (real_name != real_file_name) - free (real_name); - continue; - } - else if (opt_build_cache) - add_to_aux_cache (&lstat_buf, flag, osversion, soname); - } - - if (soname == NULL) - soname = implicit_soname (direntry->d_name, flag); - - /* A link may just point to itself. */ - if (is_link) - { - /* 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) - { - len = strlen (real_base_name); - if (len < strlen (".so") - || strcmp (real_base_name + len - strlen (".so"), ".so") != 0 - || strncmp (real_base_name, soname, len) != 0) - is_link = 0; - } - } - - if (real_name != real_file_name) - free (real_name); - - if (is_link) - { - free (soname); - soname = xstrdup (direntry->d_name); - } - - if (flag == FLAG_ELF - && (entry->flag == FLAG_ELF_LIBC5 - || entry->flag == FLAG_ELF_LIBC6)) - flag = entry->flag; - - /* Some sanity checks to print warnings. */ - if (opt_verbose) - { - if (flag == FLAG_ELF_LIBC5 && entry->flag != FLAG_ELF_LIBC5 - && entry->flag != FLAG_ANY) - error (0, 0, _("libc5 library %s in wrong directory"), file_name); - if (flag == FLAG_ELF_LIBC6 && entry->flag != FLAG_ELF_LIBC6 - && entry->flag != FLAG_ANY) - error (0, 0, _("libc6 library %s in wrong directory"), file_name); - if (flag == FLAG_LIBC4 && entry->flag != FLAG_LIBC4 - && entry->flag != FLAG_ANY) - error (0, 0, _("libc4 library %s in wrong directory"), file_name); - } - - /* Add library to list. */ - struct dlib_entry *dlib_ptr; - for (dlib_ptr = dlibs; dlib_ptr != NULL; dlib_ptr = dlib_ptr->next) - { - /* Is soname already in list? */ - if (strcmp (dlib_ptr->soname, soname) == 0) - { - /* Prefer a file to a link, otherwise check which one - is newer. */ - if ((!is_link && dlib_ptr->is_link) - || (is_link == dlib_ptr->is_link - && _dl_cache_libcmp (dlib_ptr->name, direntry->d_name) < 0)) - { - /* It's newer - add it. */ - /* Flag should be the same - sanity check. */ - if (dlib_ptr->flag != flag) - { - if (dlib_ptr->flag == FLAG_ELF - && (flag == FLAG_ELF_LIBC5 || flag == FLAG_ELF_LIBC6)) - dlib_ptr->flag = flag; - else if ((dlib_ptr->flag == FLAG_ELF_LIBC5 - || dlib_ptr->flag == FLAG_ELF_LIBC6) - && flag == FLAG_ELF) - dlib_ptr->flag = flag; - else - error (0, 0, _("libraries %s and %s in directory %s have same soname but different type."), - dlib_ptr->name, direntry->d_name, - entry->path); - } - free (dlib_ptr->name); - dlib_ptr->name = xstrdup (direntry->d_name); - dlib_ptr->is_link = is_link; - dlib_ptr->osversion = osversion; - } - /* Don't add this library, abort loop. */ - /* Also free soname, since it's dynamically allocated. */ - free (soname); - break; - } - } - /* Add the library if it's not already in. */ - if (dlib_ptr == NULL) - { - dlib_ptr = (struct dlib_entry *)xmalloc (sizeof (struct dlib_entry)); - dlib_ptr->name = xstrdup (direntry->d_name); - dlib_ptr->soname = soname; - dlib_ptr->flag = flag; - dlib_ptr->is_link = is_link; - dlib_ptr->osversion = osversion; - /* Add at head of list. */ - dlib_ptr->next = dlibs; - dlibs = dlib_ptr; - } - } - - closedir (dir); - - /* Now dlibs contains a list of all libs - add those to the cache - and created all symbolic links. */ - struct dlib_entry *dlib_ptr; - for (dlib_ptr = dlibs; dlib_ptr != NULL; dlib_ptr = dlib_ptr->next) - { - /* Don't create links to links. */ - if (dlib_ptr->is_link == 0) - create_links (dir_name, entry->path, dlib_ptr->name, - dlib_ptr->soname); - if (opt_build_cache) - add_to_cache (entry->path, dlib_ptr->soname, dlib_ptr->flag, - dlib_ptr->osversion, hwcap); - } - - /* Free all resources. */ - while (dlibs) - { - dlib_ptr = dlibs; - free (dlib_ptr->soname); - free (dlib_ptr->name); - dlibs = dlibs->next; - free (dlib_ptr); - } - - if (opt_chroot && dir_name) - free (dir_name); -} - -/* Search through all libraries. */ -static void -search_dirs (void) -{ - struct dir_entry *entry; - - for (entry = dir_entries; entry != NULL; entry = entry->next) - search_dir (entry); - - /* Free all allocated memory. */ - while (dir_entries) - { - entry = dir_entries; - dir_entries = dir_entries->next; - free (entry->path); - free (entry); - } -} - - -static void parse_conf_include (const char *config_file, unsigned int lineno, - bool do_chroot, const char *pattern); - -/* Parse configuration file. */ -static void -parse_conf (const char *filename, bool do_chroot) -{ - FILE *file = NULL; - char *line = NULL; - const char *canon; - size_t len = 0; - unsigned int lineno; - - if (do_chroot && opt_chroot) - { - canon = chroot_canon (opt_chroot, filename); - if (canon) - file = fopen (canon, "r"); - else - canon = filename; - } - else - { - canon = filename; - file = fopen (filename, "r"); - } - - if (file == NULL) - { - error (0, errno, _("\ -Warning: ignoring configuration file that cannot be opened: %s"), - canon); - if (canon != filename) - free ((char *) canon); - return; - } - - /* No threads use this stream. */ - __fsetlocking (file, FSETLOCKING_BYCALLER); - - if (canon != filename) - free ((char *) canon); - - lineno = 0; - do - { - ssize_t n = getline (&line, &len, file); - if (n < 0) - break; - - ++lineno; - if (line[n - 1] == '\n') - line[n - 1] = '\0'; - - /* Because the file format does not know any form of quoting we - can search forward for the next '#' character and if found - make it terminating the line. */ - *strchrnul (line, '#') = '\0'; - - /* Remove leading whitespace. NUL is no whitespace character. */ - char *cp = line; - while (isspace (*cp)) - ++cp; - - /* If the line is blank it is ignored. */ - if (cp[0] == '\0') - continue; - - if (!strncmp (cp, "include", 7) && isblank (cp[7])) - { - char *dir; - cp += 8; - while ((dir = strsep (&cp, " \t")) != NULL) - if (dir[0] != '\0') - parse_conf_include (filename, lineno, do_chroot, dir); - } - else if (!strncasecmp (cp, "hwcap", 5) && isblank (cp[5])) - { - cp += 6; - char *p, *name = NULL; - unsigned long int n = strtoul (cp, &cp, 0); - if (cp != NULL && isblank (*cp)) - while ((p = strsep (&cp, " \t")) != NULL) - if (p[0] != '\0') - { - if (name == NULL) - name = p; - else - { - name = NULL; - break; - } - } - if (name == NULL) - { - error (EXIT_FAILURE, 0, _("%s:%u: bad syntax in hwcap line"), - filename, lineno); - break; - } - if (n >= (64 - _DL_FIRST_EXTRA)) - error (EXIT_FAILURE, 0, - _("%s:%u: hwcap index %lu above maximum %u"), - filename, lineno, n, 64 - _DL_FIRST_EXTRA - 1); - if (hwcap_extra[n] == NULL) - { - for (unsigned long int h = 0; h < (64 - _DL_FIRST_EXTRA); ++h) - if (hwcap_extra[h] != NULL && !strcmp (name, hwcap_extra[h])) - error (EXIT_FAILURE, 0, - _("%s:%u: hwcap index %lu already defined as %s"), - filename, lineno, h, name); - hwcap_extra[n] = xstrdup (name); - } - else - { - if (strcmp (name, hwcap_extra[n])) - error (EXIT_FAILURE, 0, - _("%s:%u: hwcap index %lu already defined as %s"), - filename, lineno, n, hwcap_extra[n]); - if (opt_verbose) - error (0, 0, _("%s:%u: duplicate hwcap %lu %s"), - filename, lineno, n, name); - } - } - else - add_dir (cp); - } - while (!feof_unlocked (file)); - - /* Free buffer and close file. */ - free (line); - fclose (file); -} - -/* Handle one word in an `include' line, a glob pattern of additional - config files to read. */ -static void -parse_conf_include (const char *config_file, unsigned int lineno, - bool do_chroot, const char *pattern) -{ - if (opt_chroot && pattern[0] != '/') - error (EXIT_FAILURE, 0, - _("need absolute file name for configuration file when using -r")); - - char *copy = NULL; - if (pattern[0] != '/' && strchr (config_file, '/') != NULL) - { - if (asprintf (©, "%s/%s", dirname (strdupa (config_file)), - pattern) < 0) - error (EXIT_FAILURE, 0, _("memory exhausted")); - pattern = copy; - } - - glob64_t gl; - int result; - if (do_chroot && opt_chroot) - { - char *canon = chroot_canon (opt_chroot, pattern); - if (canon == NULL) - return; - result = glob64 (canon, 0, NULL, &gl); - free (canon); - } - else - result = glob64 (pattern, 0, NULL, &gl); - - switch (result) - { - case 0: - for (size_t i = 0; i < gl.gl_pathc; ++i) - parse_conf (gl.gl_pathv[i], false); - globfree64 (&gl); - break; - - case GLOB_NOMATCH: - break; - - case GLOB_NOSPACE: - errno = ENOMEM; - case GLOB_ABORTED: - if (opt_verbose) - error (0, errno, _("%s:%u: cannot read directory %s"), - config_file, lineno, pattern); - break; - - default: - abort (); - break; - } - - free (copy); -} - -/* Honour LD_HWCAP_MASK. */ -static void -set_hwcap (void) -{ - char *mask = getenv ("LD_HWCAP_MASK"); - - if (mask) - hwcap_mask = strtoul (mask, NULL, 0); -} - - -int -main (int argc, char **argv) -{ - /* Set locale via LC_ALL. */ - setlocale (LC_ALL, ""); - - /* Set the text message domain. */ - textdomain (_libc_intl_domainname); - - /* Parse and process arguments. */ - int remaining; - argp_parse (&argp, argc, argv, 0, &remaining, NULL); - - /* Remaining arguments are additional directories if opt_manual_link - is not set. */ - if (remaining != argc && !opt_manual_link) - { - int i; - for (i = remaining; i < argc; ++i) - if (opt_build_cache && argv[i][0] != '/') - error (EXIT_FAILURE, 0, - _("relative path `%s' used to build cache"), - argv[i]); - else - add_dir (argv[i]); - } - - /* The last entry in hwcap_extra is reserved for the "tls" pseudo-hwcap which - indicates support for TLS. This pseudo-hwcap is only used by old versions - under which TLS support was optional. The entry is no longer needed, but - must remain for compatibility. */ - hwcap_extra[63 - _DL_FIRST_EXTRA] = "tls"; - - set_hwcap (); - - if (opt_chroot) - { - /* Normalize the path a bit, we might need it for printing later. */ - char *endp = rawmemchr (opt_chroot, '\0'); - while (endp > opt_chroot && endp[-1] == '/') - --endp; - *endp = '\0'; - if (endp == opt_chroot) - opt_chroot = NULL; - - if (opt_chroot) - { - /* It is faster to use chroot if we can. */ - if (!chroot (opt_chroot)) - { - if (chdir ("/")) - error (EXIT_FAILURE, errno, _("Can't chdir to /")); - opt_chroot = NULL; - } - } - } - - if (cache_file == NULL) - { - cache_file = alloca (strlen (LD_SO_CACHE) + 1); - strcpy (cache_file, LD_SO_CACHE); - } - - if (config_file == NULL) - config_file = LD_SO_CONF; - - if (opt_print_cache) - { - if (opt_chroot) - { - char *p = chroot_canon (opt_chroot, cache_file); - if (p == NULL) - error (EXIT_FAILURE, errno, _("Can't open cache file %s\n"), - cache_file); - cache_file = p; - } - print_cache (cache_file); - if (opt_chroot) - free (cache_file); - exit (0); - } - - if (opt_chroot) - { - /* Canonicalize the directory name of cache_file, not cache_file, - because we'll rename a temporary cache file to it. */ - char *p = strrchr (cache_file, '/'); - char *canon = chroot_canon (opt_chroot, - p ? (*p = '\0', cache_file) : "/"); - - if (canon == NULL) - error (EXIT_FAILURE, errno, - _("Can't open cache file directory %s\n"), - p ? cache_file : "/"); - - if (p) - ++p; - else - p = cache_file; - - cache_file = alloca (strlen (canon) + strlen (p) + 2); - sprintf (cache_file, "%s/%s", canon, p); - free (canon); - } - - if (opt_manual_link) - { - /* Link all given libraries manually. */ - int i; - - for (i = remaining; i < argc; ++i) - manual_link (argv[i]); - - exit (0); - } - - - if (opt_build_cache) - init_cache (); - - if (!opt_only_cline) - { - parse_conf (config_file, true); - - /* Always add the standard search paths. */ - add_system_dir (SLIBDIR); - if (strcmp (SLIBDIR, LIBDIR)) - add_system_dir (LIBDIR); - } - - const char *aux_cache_file = _PATH_LDCONFIG_AUX_CACHE; - if (opt_chroot) - aux_cache_file = chroot_canon (opt_chroot, aux_cache_file); - - if (! opt_ignore_aux_cache && aux_cache_file) - load_aux_cache (aux_cache_file); - else - init_aux_cache (); - - search_dirs (); - - if (opt_build_cache) - { - save_cache (cache_file); - if (aux_cache_file) - save_aux_cache (aux_cache_file); - } - - return 0; -} diff --git a/elf/ldd.bash.in b/elf/ldd.bash.in deleted file mode 100644 index 7dd1fccf24..0000000000 --- a/elf/ldd.bash.in +++ /dev/null @@ -1,203 +0,0 @@ -#! @BASH@ -# Copyright (C) 1996-2017 Free Software Foundation, Inc. -# This file is part of the GNU C Library. - -# The GNU C Library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. - -# The GNU C Library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. - -# You should have received a copy of the GNU Lesser General Public -# License along with the GNU C Library; if not, see -# <http://www.gnu.org/licenses/>. - - -# This is the `ldd' command, which lists what shared libraries are -# used by given dynamically-linked executables. It works by invoking the -# run-time dynamic linker as a command and setting the environment -# variable LD_TRACE_LOADED_OBJECTS to a non-empty value. - -# We should be able to find the translation right at the beginning. -TEXTDOMAIN=libc -TEXTDOMAINDIR=@TEXTDOMAINDIR@ - -RTLDLIST=@RTLD@ -warn= -bind_now= -verbose= - -while test $# -gt 0; do - case "$1" in - --vers | --versi | --versio | --version) - echo 'ldd @PKGVERSION@@VERSION@' - 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. -" "2017" - printf $"Written by %s and %s. -" "Roland McGrath" "Ulrich Drepper" - exit 0 - ;; - --h | --he | --hel | --help) - echo $"Usage: ldd [OPTION]... FILE... - --help print this help and exit - --version print version information and exit - -d, --data-relocs process data relocations - -r, --function-relocs process data and function relocations - -u, --unused print unused direct dependencies - -v, --verbose print all information -" - printf $"For bug reporting instructions, please see:\\n%s.\\n" \ - "@REPORT_BUGS_TO@" - exit 0 - ;; - -d | --d | --da | --dat | --data | --data- | --data-r | --data-re | \ - --data-rel | --data-relo | --data-reloc | --data-relocs) - warn=yes - shift - ;; - -r | --f | --fu | --fun | --func | --funct | --functi | --functio | \ - --function | --function- | --function-r | --function-re | --function-rel | \ - --function-relo | --function-reloc | --function-relocs) - warn=yes - bind_now=yes - shift - ;; - -v | --verb | --verbo | --verbos | --verbose) - verbose=yes - shift - ;; - -u | --u | --un | --unu | --unus | --unuse | --unused) - unused=yes - shift - ;; - --v | --ve | --ver) - echo >&2 $"ldd: option \`$1' is ambiguous" - exit 1 - ;; - --) # Stop option processing. - shift; break - ;; - -*) - echo >&2 'ldd:' $"unrecognized option" "\`$1'" - echo >&2 $"Try \`ldd --help' for more information." - exit 1 - ;; - *) - break - ;; - esac -done - -nonelf () -{ - # Maybe extra code for non-ELF binaries. - return 1; -} - -add_env="LD_TRACE_LOADED_OBJECTS=1 LD_WARN=$warn LD_BIND_NOW=$bind_now" -add_env="$add_env LD_VERBOSE=$verbose" -if test "$unused" = yes; then - add_env="$add_env LD_DEBUG=\"$LD_DEBUG${LD_DEBUG:+,}unused\"" -fi - -# The following command substitution is needed to make ldd work in SELinux -# environments where the RTLD might not have permission to write to the -# terminal. The extra "x" character prevents the shell from trimming trailing -# newlines from command substitution results. This function is defined as a -# subshell compound list (using "(...)") to prevent parameter assignments from -# affecting the calling shell execution environment. -try_trace() ( - output=$(eval $add_env '"$@"' 2>&1; rc=$?; printf 'x'; exit $rc) - rc=$? - printf '%s' "${output%x}" - return $rc -) - -case $# in -0) - echo >&2 'ldd:' $"missing file arguments" - echo >&2 $"Try \`ldd --help' for more information." - exit 1 - ;; -1) - single_file=t - ;; -*) - single_file=f - ;; -esac - -result=0 -for file do - # We don't list the file name when there is only one. - test $single_file = t || echo "${file}:" - case $file in - */*) : - ;; - *) file=./$file - ;; - esac - if test ! -e "$file"; then - echo "ldd: ${file}:" $"No such file or directory" >&2 - result=1 - elif test ! -f "$file"; then - echo "ldd: ${file}:" $"not regular file" >&2 - result=1 - elif test -r "$file"; then - test -x "$file" || echo 'ldd:' $"\ -warning: you do not have execution permission for" "\`$file'" >&2 - RTLD= - ret=1 - for rtld in ${RTLDLIST}; do - if test -x $rtld; then - verify_out=`${rtld} --verify "$file"` - ret=$? - case $ret in - [02]) RTLD=${rtld}; break;; - esac - fi - done - case $ret in - 0) - # If the program exits with exit code 5, it means the process has been - # invoked with __libc_enable_secure. Fall back to running it through - # the dynamic linker. - try_trace "$file" - rc=$? - if [ $rc = 5 ]; then - try_trace "$RTLD" "$file" - rc=$? - fi - [ $rc = 0 ] || result=1 - ;; - 1) - # This can be a non-ELF binary or no binary at all. - nonelf "$file" || { - echo $" not a dynamic executable" - result=1 - } - ;; - 2) - try_trace "$RTLD" "$file" || result=1 - ;; - *) - echo 'ldd:' ${RTLD} $"exited with unknown exit code" "($ret)" >&2 - exit 1 - ;; - esac - else - echo 'ldd:' $"error: you do not have read permission for" "\`$file'" >&2 - result=1 - fi -done - -exit $result -# Local Variables: -# mode:ksh -# End: diff --git a/elf/link.h b/elf/link.h deleted file mode 100644 index 0e223ce9f0..0000000000 --- a/elf/link.h +++ /dev/null @@ -1,194 +0,0 @@ -/* Data structure for communication from the run-time dynamic linker for - loaded ELF shared objects. - Copyright (C) 1995-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -#ifndef _LINK_H -#define _LINK_H 1 - -#include <features.h> -#include <elf.h> -#include <dlfcn.h> -#include <sys/types.h> - -/* We use this macro to refer to ELF types independent of the native wordsize. - `ElfW(TYPE)' is used in place of `Elf32_TYPE' or `Elf64_TYPE'. */ -#define ElfW(type) _ElfW (Elf, __ELF_NATIVE_CLASS, type) -#define _ElfW(e,w,t) _ElfW_1 (e, w, _##t) -#define _ElfW_1(e,w,t) e##w##t - -#include <bits/elfclass.h> /* Defines __ELF_NATIVE_CLASS. */ -#include <bits/link.h> - -/* Rendezvous structure used by the run-time dynamic linker to communicate - details of shared object loading to the debugger. If the executable's - dynamic section has a DT_DEBUG element, the run-time linker sets that - element's value to the address where this structure can be found. */ - -struct r_debug - { - int r_version; /* Version number for this protocol. */ - - struct link_map *r_map; /* Head of the chain of loaded objects. */ - - /* This is the address of a function internal to the run-time linker, - that will always be called when the linker begins to map in a - library or unmap it, and again when the mapping change is complete. - The debugger can set a breakpoint at this address if it wants to - notice shared object mapping changes. */ - ElfW(Addr) r_brk; - enum - { - /* This state value describes the mapping change taking place when - the `r_brk' address is called. */ - RT_CONSISTENT, /* Mapping change is complete. */ - RT_ADD, /* Beginning to add a new object. */ - RT_DELETE /* Beginning to remove an object mapping. */ - } r_state; - - ElfW(Addr) r_ldbase; /* Base address the linker is loaded at. */ - }; - -/* This is the instance of that structure used by the dynamic linker. */ -extern struct r_debug _r_debug; - -/* This symbol refers to the "dynamic structure" in the `.dynamic' section - of whatever module refers to `_DYNAMIC'. So, to find its own - `struct r_debug', a program could do: - for (dyn = _DYNAMIC; dyn->d_tag != DT_NULL; ++dyn) - if (dyn->d_tag == DT_DEBUG) - r_debug = (struct r_debug *) dyn->d_un.d_ptr; - */ -extern ElfW(Dyn) _DYNAMIC[]; - -/* Structure describing a loaded shared object. The `l_next' and `l_prev' - members form a chain of all the shared objects loaded at startup. - - These data structures exist in space used by the run-time dynamic linker; - modifying them may have disastrous results. */ - -struct link_map - { - /* These first few members are part of the protocol with the debugger. - This is the same format used in SVR4. */ - - ElfW(Addr) l_addr; /* Difference between the address in the ELF - file and the addresses in memory. */ - char *l_name; /* Absolute file name object was found in. */ - ElfW(Dyn) *l_ld; /* Dynamic section of the shared object. */ - struct link_map *l_next, *l_prev; /* Chain of loaded objects. */ - }; - -#ifdef __USE_GNU - -/* Version numbers for la_version handshake interface. */ -#define LAV_CURRENT 1 - -/* Activity types signaled through la_activity. */ -enum - { - LA_ACT_CONSISTENT, /* Link map consistent again. */ - LA_ACT_ADD, /* New object will be added. */ - LA_ACT_DELETE /* Objects will be removed. */ - }; - -/* Values representing origin of name for dynamic loading. */ -enum - { - LA_SER_ORIG = 0x01, /* Original name. */ - LA_SER_LIBPATH = 0x02, /* Directory from LD_LIBRARY_PATH. */ - LA_SER_RUNPATH = 0x04, /* Directory from RPATH/RUNPATH. */ - LA_SER_CONFIG = 0x08, /* Found through ldconfig. */ - LA_SER_DEFAULT = 0x40, /* Default directory. */ - LA_SER_SECURE = 0x80 /* Unused. */ - }; - -/* Values for la_objopen return value. */ -enum - { - LA_FLG_BINDTO = 0x01, /* Audit symbols bound to this object. */ - LA_FLG_BINDFROM = 0x02 /* Audit symbols bound from this object. */ - }; - -/* Values for la_symbind flags parameter. */ -enum - { - LA_SYMB_NOPLTENTER = 0x01, /* la_pltenter will not be called. */ - LA_SYMB_NOPLTEXIT = 0x02, /* la_pltexit will not be called. */ - LA_SYMB_STRUCTCALL = 0x04, /* Return value is a structure. */ - LA_SYMB_DLSYM = 0x08, /* Binding due to dlsym call. */ - LA_SYMB_ALTVALUE = 0x10 /* Value has been changed by a previous - la_symbind call. */ - }; - -struct dl_phdr_info - { - ElfW(Addr) dlpi_addr; - const char *dlpi_name; - const ElfW(Phdr) *dlpi_phdr; - ElfW(Half) dlpi_phnum; - - /* Note: Following members were introduced after the first - version of this structure was available. Check the SIZE - argument passed to the dl_iterate_phdr callback to determine - whether or not each later member is available. */ - - /* Incremented when a new object may have been added. */ - __extension__ unsigned long long int dlpi_adds; - /* Incremented when an object may have been removed. */ - __extension__ unsigned long long int dlpi_subs; - - /* If there is a PT_TLS segment, its module ID as used in - TLS relocations, else zero. */ - size_t dlpi_tls_modid; - - /* The address of the calling thread's instance of this module's - PT_TLS segment, if it has one and it has been allocated - in the calling thread, otherwise a null pointer. */ - void *dlpi_tls_data; - }; - -__BEGIN_DECLS - -extern int dl_iterate_phdr (int (*__callback) (struct dl_phdr_info *, - size_t, void *), - void *__data); - - -/* Prototypes for the ld.so auditing interfaces. These are not - defined anywhere in ld.so but instead have to be provided by the - auditing DSO. */ -extern unsigned int la_version (unsigned int __version); -extern void la_activity (uintptr_t *__cookie, unsigned int __flag); -extern char *la_objsearch (const char *__name, uintptr_t *__cookie, - unsigned int __flag); -extern unsigned int la_objopen (struct link_map *__map, Lmid_t __lmid, - uintptr_t *__cookie); -extern void la_preinit (uintptr_t *__cookie); -extern uintptr_t la_symbind32 (Elf32_Sym *__sym, unsigned int __ndx, - uintptr_t *__refcook, uintptr_t *__defcook, - unsigned int *__flags, const char *__symname); -extern uintptr_t la_symbind64 (Elf64_Sym *__sym, unsigned int __ndx, - uintptr_t *__refcook, uintptr_t *__defcook, - unsigned int *__flags, const char *__symname); -extern unsigned int la_objclose (uintptr_t *__cookie); - -__END_DECLS - -#endif - -#endif /* link.h */ diff --git a/elf/loadfail.c b/elf/loadfail.c deleted file mode 100644 index 7531aa958e..0000000000 --- a/elf/loadfail.c +++ /dev/null @@ -1,42 +0,0 @@ -#include <dlfcn.h> -#include <error.h> -#include <mcheck.h> -#include <stdio.h> -#include <stdlib.h> - -int -main (void) -{ - void *su[5]; - void *h; - int n; - - mtrace (); - - if ((su[0] = dlopen ("testobj1.so", RTLD_GLOBAL | RTLD_NOW)) == NULL - || (su[1] = dlopen ("testobj2.so", RTLD_GLOBAL | RTLD_NOW)) == NULL - || (su[2] = dlopen ("testobj3.so", RTLD_GLOBAL | RTLD_NOW)) == NULL - || (su[3] = dlopen ("testobj4.so", RTLD_GLOBAL | RTLD_NOW)) == NULL - || (su[4] = dlopen ("testobj5.so", RTLD_GLOBAL | RTLD_NOW)) == NULL) - error (EXIT_FAILURE, 0, "failed to load shared object: %s", dlerror ()); - - h = dlopen ("failobj.so", RTLD_GLOBAL | RTLD_NOW); - - printf ("h = %p, %s\n", h, h == NULL ? "ok" : "fail"); - - for (n = 0; n < 5; ++n) - if (dlclose (su[n]) != 0) - { - printf ("failed to unload su[%d]: %s\n", n, dlerror ()); - exit (EXIT_FAILURE); - } - - return h != NULL; -} - -extern int foo (int a); -int -foo (int a) -{ - return 10; -} diff --git a/elf/loadtest.c b/elf/loadtest.c deleted file mode 100644 index 727469b496..0000000000 --- a/elf/loadtest.c +++ /dev/null @@ -1,202 +0,0 @@ -#include <assert.h> -#include <dlfcn.h> -#include <errno.h> -#include <error.h> -#include <mcheck.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - - -/* How many load/unload operations do we do. */ -#define TEST_ROUNDS 1000 - - -static struct -{ - /* Name of the module. */ - const char *name; - /* The handle. */ - void *handle; -} testobjs[] = -{ - { "testobj1.so", NULL }, - { "testobj2.so", NULL }, - { "testobj3.so", NULL }, - { "testobj4.so", NULL }, - { "testobj5.so", NULL }, - { "testobj6.so", NULL }, -}; -#define NOBJS (sizeof (testobjs) / sizeof (testobjs[0])) - - -static const struct -{ - /* Name of a function to call. */ - const char *fname; - /* Index in status and handle array. */ - int index; - /* Options while loading the module. */ - int options; -} tests[] = -{ - { "obj1func2", 0, RTLD_LAZY }, - { "obj1func1", 0, RTLD_LAZY | RTLD_GLOBAL }, - { "obj1func1", 0, RTLD_NOW, }, - { "obj1func2", 0, RTLD_NOW | RTLD_GLOBAL }, - { "obj2func2", 1, RTLD_LAZY }, - { "obj2func1", 1, RTLD_LAZY | RTLD_GLOBAL, }, - { "obj2func1", 1, RTLD_NOW, }, - { "obj2func2", 1, RTLD_NOW | RTLD_GLOBAL }, - { "obj3func2", 2, RTLD_LAZY }, - { "obj3func1", 2, RTLD_LAZY | RTLD_GLOBAL }, - { "obj3func1", 2, RTLD_NOW }, - { "obj3func2", 2, RTLD_NOW | RTLD_GLOBAL }, - { "obj4func2", 3, RTLD_LAZY }, - { "obj4func1", 3, RTLD_LAZY | RTLD_GLOBAL }, - { "obj4func1", 3, RTLD_NOW }, - { "obj4func2", 3, RTLD_NOW | RTLD_GLOBAL }, - { "obj5func2", 4, RTLD_LAZY }, - { "obj5func1", 4, RTLD_LAZY | RTLD_GLOBAL }, - { "obj5func1", 4, RTLD_NOW }, - { "obj5func2", 4, RTLD_NOW | RTLD_GLOBAL }, - { "obj6func2", 5, RTLD_LAZY }, - { "obj6func1", 5, RTLD_LAZY | RTLD_GLOBAL }, - { "obj6func1", 5, RTLD_NOW }, - { "obj6func2", 5, RTLD_NOW | RTLD_GLOBAL }, -}; -#define NTESTS (sizeof (tests) / sizeof (tests[0])) - - -#include <include/link.h> - -#define MAPS ((struct link_map *) _r_debug.r_map) - -#define OUT \ - for (map = MAPS; map != NULL; map = map->l_next) \ - if (map->l_type == lt_loaded) \ - printf ("name = \"%s\", direct_opencount = %d\n", \ - map->l_name, (int) map->l_direct_opencount); \ - fflush (stdout) - - -int -main (int argc, char *argv[]) -{ - int debug = argc > 1 && argv[1][0] != '\0'; - int count = TEST_ROUNDS; - int result = 0; - struct link_map *map; - - mtrace (); - - /* Just a seed. */ - srandom (TEST_ROUNDS); - - if (debug) - { - puts ("in the beginning"); - OUT; - } - - while (count--) - { - int nr = random () % NTESTS; - int index = tests[nr].index; - - printf ("%4d: %4d: ", count + 1, nr); - fflush (stdout); - - if (testobjs[index].handle == NULL) - { - int (*fct) (int); - - /* Load the object. */ - testobjs[index].handle = dlopen (testobjs[index].name, - tests[nr].options); - if (testobjs[index].handle == NULL) - error (EXIT_FAILURE, 0, "cannot load `%s': %s", - testobjs[index].name, dlerror ()); - - /* Test the function call. */ - fct = dlsym (testobjs[index].handle, tests[nr].fname); - if (fct == NULL) - error (EXIT_FAILURE, 0, - "cannot get function `%s' from shared object `%s': %s", - tests[nr].fname, testobjs[index].name, dlerror ()); - - fct (10); - - printf ("successfully loaded `%s', handle %p\n", - testobjs[index].name, testobjs[index].handle); - } - else - { - if (dlclose (testobjs[index].handle) != 0) - { - printf ("failed to close %s\n", testobjs[index].name); - result = 1; - } - else - printf ("successfully unloaded `%s', handle %p\n", - testobjs[index].name, testobjs[index].handle); - - testobjs[index].handle = NULL; - - if (testobjs[0].handle == NULL - && testobjs[1].handle == NULL - && testobjs[5].handle == NULL) - { - /* In this case none of the objects above should be - present. */ - for (map = MAPS; map != NULL; map = map->l_next) - if (map->l_type == lt_loaded - && (strstr (map->l_name, testobjs[0].name) != NULL - || strstr (map->l_name, testobjs[1].name) != NULL - || strstr (map->l_name, testobjs[5].name) != NULL)) - { - printf ("`%s' is still loaded\n", map->l_name); - result = 1; - } - } - } - - if (debug) - OUT; - } - - /* Unload all loaded modules. */ - for (count = 0; count < (int) NOBJS; ++count) - if (testobjs[count].handle != NULL) - { - printf ("\nclose: %s: l_initfini = %p, l_versions = %p\n", - testobjs[count].name, - ((struct link_map *) testobjs[count].handle)->l_initfini, - ((struct link_map *) testobjs[count].handle)->l_versions); - - if (dlclose (testobjs[count].handle) != 0) - { - printf ("failed to close %s\n", testobjs[count].name); - result = 1; - } - } - - /* Check whether all files are unloaded. */ - for (map = MAPS; map != NULL; map = map->l_next) - if (map->l_type == lt_loaded) - { - printf ("name = \"%s\", direct_opencount = %d\n", - map->l_name, (int) map->l_direct_opencount); - result = 1; - } - - return result; -} - - -extern int foo (int a); -int -foo (int a) -{ - return a - 1; -} diff --git a/elf/ltglobmod1.c b/elf/ltglobmod1.c deleted file mode 100644 index 300fa9a89f..0000000000 --- a/elf/ltglobmod1.c +++ /dev/null @@ -1,7 +0,0 @@ -extern int bar (void); - -int -bar (void) -{ - return 42; -} diff --git a/elf/ltglobmod2.c b/elf/ltglobmod2.c deleted file mode 100644 index 33f14cc980..0000000000 --- a/elf/ltglobmod2.c +++ /dev/null @@ -1,33 +0,0 @@ -#include <dlfcn.h> -#include <stdio.h> -#include <stdlib.h> - -extern int bar (void); -extern int foo (void); - -int -foo (void) -{ - void *h; - int res; - - /* Load ltglobalmod1 in the global namespace. */ - h = dlopen ("ltglobmod1.so", RTLD_GLOBAL | RTLD_LAZY); - if (h == NULL) - { - printf ("%s: cannot open %s: %s", - __FUNCTION__, "ltglobmod1.so", dlerror ()); - exit (EXIT_FAILURE); - } - - /* Call bar. This is undefined in the DSO. */ - puts ("about to call `bar'"); - fflush (stdout); - res = bar (); - - printf ("bar returned %d\n", res); - - dlclose (h); - - return res != 42; -} diff --git a/elf/multiload.c b/elf/multiload.c deleted file mode 100644 index e85cc96589..0000000000 --- a/elf/multiload.c +++ /dev/null @@ -1,105 +0,0 @@ -#include <dlfcn.h> -#include <errno.h> -#include <mcheck.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -int -main (void) -{ - void *a; - void *b; - void *c; - void *d; - char *wd; - char *base; - char *buf; - - mtrace (); - - /* Change to the binary directory. */ - if (chdir (OBJDIR) != 0) - { - printf ("cannot change to `%s': %m", OBJDIR); - exit (EXIT_FAILURE); - } - - wd = getcwd (NULL, 0); - base = basename (wd); - buf = alloca (strlen (wd) + strlen (base) + 5 + sizeof "testobj1.so"); - - printf ("loading `%s'\n", "./testobj1.so"); - a = dlopen ("./testobj1.so", RTLD_NOW); - if (a == NULL) - { - printf ("cannot load `./testobj1.so': %s\n", dlerror ()); - exit (EXIT_FAILURE); - } - - stpcpy (stpcpy (stpcpy (buf, "../"), base), "/testobj1.so"); - printf ("loading `%s'\n", buf); - b = dlopen (buf, RTLD_NOW); - if (b == NULL) - { - printf ("cannot load `%s': %s\n", buf, dlerror ()); - exit (EXIT_FAILURE); - } - - stpcpy (stpcpy (buf, wd), "/testobj1.so"); - printf ("loading `%s'\n", buf); - c = dlopen (buf, RTLD_NOW); - if (c == NULL) - { - printf ("cannot load `%s': %s\n", buf, dlerror ()); - exit (EXIT_FAILURE); - } - - stpcpy (stpcpy (stpcpy (stpcpy (buf, wd), "/../"), base), "/testobj1.so"); - printf ("loading `%s'\n", buf); - d = dlopen (buf, RTLD_NOW); - if (d == NULL) - { - printf ("cannot load `%s': %s\n", buf, dlerror ()); - exit (EXIT_FAILURE); - } - - if (a != b || b != c || c != d) - { - puts ("shared object loaded more than once"); - exit (EXIT_FAILURE); - } - - if (dlclose (a) != 0) - { - puts ("closing `a' failed"); - exit (EXIT_FAILURE); - } - if (dlclose (b) != 0) - { - puts ("closing `a' failed"); - exit (EXIT_FAILURE); - } - if (dlclose (c) != 0) - { - puts ("closing `a' failed"); - exit (EXIT_FAILURE); - } - if (dlclose (d) != 0) - { - puts ("closing `a' failed"); - exit (EXIT_FAILURE); - } - - free (wd); - - return 0; -} - -extern int foo (int a); -int -foo (int a) -{ - return a; -} diff --git a/elf/neededobj1.c b/elf/neededobj1.c deleted file mode 100644 index eb55adab39..0000000000 --- a/elf/neededobj1.c +++ /dev/null @@ -1,6 +0,0 @@ -extern void c_function (void); - -void -c_function (void) -{ -} diff --git a/elf/neededobj2.c b/elf/neededobj2.c deleted file mode 100644 index 5ad8a51d62..0000000000 --- a/elf/neededobj2.c +++ /dev/null @@ -1,8 +0,0 @@ -extern void b_function (void); -extern void c_function (void); - -void -b_function (void) -{ - c_function(); -} diff --git a/elf/neededobj3.c b/elf/neededobj3.c deleted file mode 100644 index da25329aa7..0000000000 --- a/elf/neededobj3.c +++ /dev/null @@ -1,10 +0,0 @@ -extern void a_function (void); -extern void b_function (void); -extern void c_function (void); - -void -a_function (void) -{ - b_function (); - c_function (); -} diff --git a/elf/neededobj4.c b/elf/neededobj4.c deleted file mode 100644 index 3ea8540047..0000000000 --- a/elf/neededobj4.c +++ /dev/null @@ -1,12 +0,0 @@ -extern void a_function (void); -extern void b_function (void); -extern void c_function (void); -extern void d_function (void); - -void -d_function (void) -{ - a_function (); - b_function (); - c_function (); -} diff --git a/elf/neededobj5.c b/elf/neededobj5.c deleted file mode 100644 index 2d629b0880..0000000000 --- a/elf/neededobj5.c +++ /dev/null @@ -1,5 +0,0 @@ -extern void a1_function (void); - -void a1_function (void) -{ -} diff --git a/elf/neededobj6.c b/elf/neededobj6.c deleted file mode 100644 index 639b6f195e..0000000000 --- a/elf/neededobj6.c +++ /dev/null @@ -1,7 +0,0 @@ -extern void a1_function (void); -extern void a2_function (void); - -void a2_function (void) -{ - a1_function (); -} diff --git a/elf/neededtest.c b/elf/neededtest.c deleted file mode 100644 index 3cea499314..0000000000 --- a/elf/neededtest.c +++ /dev/null @@ -1,125 +0,0 @@ -#include <dlfcn.h> -#include <libintl.h> -#include <link.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#define MAPS ((struct link_map *) _r_debug.r_map) - -static int -check_loaded_objects (const char **loaded) -{ - struct link_map *lm; - int n; - int *found = NULL; - int errors = 0; - - for (n = 0; loaded[n]; n++) - /* NOTHING */; - - if (n) - { - found = (int *) alloca (sizeof (int) * n); - memset (found, 0, sizeof (int) * n); - } - - printf(" Name\n"); - printf(" --------------------------------------------------------\n"); - for (lm = MAPS; lm; lm = lm->l_next) - { - if (lm->l_name && lm->l_name[0]) - printf(" %s, count = %d\n", lm->l_name, (int) lm->l_direct_opencount); - if (lm->l_type == lt_loaded && lm->l_name) - { - int match = 0; - for (n = 0; loaded[n] != NULL; n++) - { - if (strcmp (basename (loaded[n]), basename (lm->l_name)) == 0) - { - found[n] = 1; - match = 1; - break; - } - } - - if (match == 0) - { - ++errors; - printf ("ERRORS: %s is not unloaded\n", lm->l_name); - } - } - } - - for (n = 0; loaded[n] != NULL; n++) - { - if (found[n] == 0) - { - ++errors; - printf ("ERRORS: %s is not loaded\n", loaded[n]); - } - } - - return errors; -} - -int -main (void) -{ - void *obj2[2]; - void *obj3; - const char *loaded[] = { NULL, NULL, NULL, NULL }; - int errors = 0; - - printf ("\nThis is what is in memory now:\n"); - errors += check_loaded_objects (loaded); - - printf( "Loading shared object neededobj3.so\n"); - obj3 = dlopen( "neededobj3.so", RTLD_LAZY); - if (obj3 == NULL) - { - printf ("%s\n", dlerror ()); - exit (1); - } - loaded[0] = "neededobj1.so"; - loaded[1] = "neededobj2.so"; - loaded[2] = "neededobj3.so"; - errors += check_loaded_objects (loaded); - - printf ("Now loading shared object neededobj2.so\n"); - obj2[0] = dlopen ("neededobj2.so", RTLD_LAZY); - if (obj2[0] == NULL) - { - printf ("%s\n", dlerror ()); - exit (1); - } - errors += check_loaded_objects (loaded); - - printf ("And loading shared object neededobj2.so again\n"); - obj2[1] = dlopen ("neededobj2.so", RTLD_LAZY); - if (obj2[1] == NULL) - { - printf ("%s\n", dlerror ()); - exit (1); - } - errors += check_loaded_objects (loaded); - - printf ("Closing neededobj2.so for the first time\n"); - dlclose (obj2[0]); - errors += check_loaded_objects (loaded); - - printf ("Closing neededobj3.so\n"); - dlclose (obj3); - loaded[2] = NULL; - errors += check_loaded_objects (loaded); - - printf ("Closing neededobj2.so for the second time\n"); - dlclose (obj2[1]); - loaded[0] = NULL; - loaded[1] = NULL; - errors += check_loaded_objects (loaded); - - if (errors != 0) - printf ("%d errors found\n", errors); - return errors; -} diff --git a/elf/neededtest2.c b/elf/neededtest2.c deleted file mode 100644 index 17c75f2ba3..0000000000 --- a/elf/neededtest2.c +++ /dev/null @@ -1,118 +0,0 @@ -#include <dlfcn.h> -#include <libintl.h> -#include <link.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#define MAPS ((struct link_map *) _r_debug.r_map) - -static int -check_loaded_objects (const char **loaded) -{ - struct link_map *lm; - int n; - int *found = NULL; - int errors = 0; - - for (n = 0; loaded[n]; n++) - /* NOTHING */; - - if (n) - { - found = (int *) alloca (sizeof (int) * n); - memset (found, 0, sizeof (int) * n); - } - - printf(" Name\n"); - printf(" --------------------------------------------------------\n"); - for (lm = MAPS; lm; lm = lm->l_next) - { - if (lm->l_name && lm->l_name[0]) - printf(" %s, count = %d\n", lm->l_name, (int) lm->l_direct_opencount); - if (lm->l_type == lt_loaded && lm->l_name) - { - int match = 0; - for (n = 0; loaded[n] != NULL; n++) - { - if (strcmp (basename (loaded[n]), basename (lm->l_name)) == 0) - { - found[n] = 1; - match = 1; - break; - } - } - - if (match == 0) - { - ++errors; - printf ("ERRORS: %s is not unloaded\n", lm->l_name); - } - } - } - - for (n = 0; loaded[n] != NULL; n++) - { - if (found[n] == 0) - { - ++errors; - printf ("ERRORS: %s is not loaded\n", loaded[n]); - } - } - - return errors; -} - -int -main (void) -{ - void *obj2; - void *obj3[2]; - const char *loaded[] = { NULL, NULL, NULL, NULL }; - int errors = 0; - - printf ("\nThis is what is in memory now:\n"); - errors += check_loaded_objects (loaded); - printf ("\nLoading shared object neededobj2.so\n"); - obj2 = dlopen ("neededobj2.so", RTLD_LAZY); - if (obj2 == NULL) - { - printf ("%s\n", dlerror ()); - exit (1); - } - loaded[0] = "neededobj1.so"; - loaded[1] = "neededobj2.so"; - errors += check_loaded_objects (loaded); - printf ("\nLoading shared object neededobj3.so\n"); - obj3[0] = dlopen( "neededobj3.so", RTLD_LAZY); - if (obj3[0] == NULL) - { - printf ("%s\n", dlerror ()); - exit (1); - } - loaded[2] = "neededobj3.so"; - errors += check_loaded_objects (loaded); - printf ("\nNow loading shared object neededobj3.so again\n"); - obj3[1] = dlopen ("neededobj3.so", RTLD_LAZY); - if (obj3[1] == NULL) - { - printf ("%s\n", dlerror ()); - exit (1); - } - errors += check_loaded_objects (loaded); - printf ("\nClosing neededobj3.so once\n"); - dlclose (obj3[0]); - errors += check_loaded_objects (loaded); - printf ("\nClosing neededobj2.so\n"); - dlclose (obj2); - errors += check_loaded_objects (loaded); - printf ("\nClosing neededobj3.so for the second time\n"); - dlclose (obj3[1]); - loaded[0] = NULL; - loaded[1] = NULL; - loaded[2] = NULL; - errors += check_loaded_objects (loaded); - if (errors != 0) - printf ("%d errors found\n", errors); - return errors; -} diff --git a/elf/neededtest3.c b/elf/neededtest3.c deleted file mode 100644 index 41970cf2c7..0000000000 --- a/elf/neededtest3.c +++ /dev/null @@ -1,129 +0,0 @@ -#include <dlfcn.h> -#include <libintl.h> -#include <link.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#define MAPS ((struct link_map *) _r_debug.r_map) - -static int -check_loaded_objects (const char **loaded) -{ - struct link_map *lm; - int n; - int *found = NULL; - int errors = 0; - - for (n = 0; loaded[n]; n++) - /* NOTHING */; - - if (n) - { - found = (int *) alloca (sizeof (int) * n); - memset (found, 0, sizeof (int) * n); - } - - printf(" Name\n"); - printf(" --------------------------------------------------------\n"); - for (lm = MAPS; lm; lm = lm->l_next) - { - if (lm->l_name && lm->l_name[0]) - printf(" %s, count = %d\n", lm->l_name, (int) lm->l_direct_opencount); - if (lm->l_type == lt_loaded && lm->l_name) - { - int match = 0; - for (n = 0; loaded[n] != NULL; n++) - { - if (strcmp (basename (loaded[n]), basename (lm->l_name)) == 0) - { - found[n] = 1; - match = 1; - break; - } - } - - if (match == 0) - { - ++errors; - printf ("ERRORS: %s is not unloaded\n", lm->l_name); - } - } - } - - for (n = 0; loaded[n] != NULL; n++) - { - if (found[n] == 0) - { - ++errors; - printf ("ERRORS: %s is not loaded\n", loaded[n]); - } - } - - return errors; -} - -int -main (void) -{ - void *obj2; - void *obj3; - void *obj4; - const char *loaded[] = { NULL, NULL, NULL, NULL, NULL }; - int errors = 0; - - printf ("\nThis is what is in memory now:\n"); - errors += check_loaded_objects (loaded); - - printf ("Now loading shared object neededobj2.so\n"); - obj2 = dlopen ("neededobj2.so", RTLD_LAZY); - if (obj2 == NULL) - { - printf ("%s\n", dlerror ()); - exit (1); - } - loaded[0] = "neededobj1.so"; - loaded[1] = "neededobj2.so"; - errors += check_loaded_objects (loaded); - - printf( "Loading shared object neededobj3.so\n"); - obj3 = dlopen( "neededobj3.so", RTLD_LAZY); - if (obj3 == NULL) - { - printf ("%s\n", dlerror ()); - exit (1); - } - loaded[2] = "neededobj3.so"; - errors += check_loaded_objects (loaded); - - - printf( "Loading shared object neededobj4.so\n"); - obj4 = dlopen( "neededobj4.so", RTLD_LAZY); - if (obj4 == NULL) - { - printf ("%s\n", dlerror ()); - exit (1); - } - loaded[3] = "neededobj4.so"; - errors += check_loaded_objects (loaded); - - printf ("Closing neededobj2.so\n"); - dlclose (obj2); - errors += check_loaded_objects (loaded); - - printf ("Closing neededobj3.so\n"); - dlclose (obj3); - errors += check_loaded_objects (loaded); - - printf ("Closing neededobj4.so\n"); - dlclose (obj4); - loaded[0] = NULL; - loaded[1] = NULL; - loaded[2] = NULL; - loaded[3] = NULL; - errors += check_loaded_objects (loaded); - - if (errors != 0) - printf ("%d errors found\n", errors); - return errors; -} diff --git a/elf/neededtest4.c b/elf/neededtest4.c deleted file mode 100644 index 0ae0b7ff47..0000000000 --- a/elf/neededtest4.c +++ /dev/null @@ -1,158 +0,0 @@ -#include <dlfcn.h> -#include <libintl.h> -#include <link.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#define MAPS ((struct link_map *) _r_debug.r_map) - -static int -check_loaded_objects (const char **loaded) -{ - struct link_map *lm; - int n; - int *found = NULL; - int errors = 0; - - for (n = 0; loaded[n]; n++) - /* NOTHING */; - - if (n) - { - found = (int *) alloca (sizeof (int) * n); - memset (found, 0, sizeof (int) * n); - } - - printf(" Name\n"); - printf(" --------------------------------------------------------\n"); - for (lm = MAPS; lm; lm = lm->l_next) - { - if (lm->l_name && lm->l_name[0]) - printf(" %s, count = %d\n", lm->l_name, (int) lm->l_direct_opencount); - if (lm->l_type == lt_loaded && lm->l_name) - { - int match = 0; - for (n = 0; loaded[n] != NULL; n++) - { - if (strcmp (basename (loaded[n]), basename (lm->l_name)) == 0) - { - found[n] = 1; - match = 1; - break; - } - } - - if (match == 0) - { - ++errors; - printf ("ERRORS: %s is not unloaded\n", lm->l_name); - } - } - } - - for (n = 0; loaded[n] != NULL; n++) - { - if (found[n] == 0) - { - ++errors; - printf ("ERRORS: %s is not loaded\n", loaded[n]); - } - } - - return errors; -} - -extern void c_function (void); -extern char *dirname (const char *__filename); - -int -main (int argc, char **argv) -{ - void *obj; - const char *loaded[] = { NULL, NULL, NULL}; - int errors = 0; - void (*f) (void); - const char *dir = dirname (argv [0]); - char *oldfilename; - char *newfilename; - - c_function (); - - printf ("\nThis is what is in memory now:\n"); - errors += check_loaded_objects (loaded); - - printf( "Loading shared object neededobj6.so\n"); - obj = dlopen( "neededobj6.so", RTLD_LAZY); - if (obj == NULL) - { - printf ("%s\n", dlerror ()); - exit (1); - } - f = dlsym (obj, "a2_function"); - if (f == NULL) - { - printf ("%s\n", dlerror ()); - exit (1); - } - f (); - loaded[0] = "neededobj5.so"; - loaded[1] = "neededobj6.so"; - errors += check_loaded_objects (loaded); - - printf ("Closing neededobj6.so\n"); - dlclose (obj); - loaded[0] = NULL; - errors += check_loaded_objects (loaded); - - printf ("Rename neededobj5.so\n"); - oldfilename = alloca (strlen (dir) + 1 + sizeof ("neededobj5.so")); - strcpy (oldfilename, dir); - strcat (oldfilename, "/"); - strcat (oldfilename, "neededobj5.so"); - newfilename = alloca (strlen (oldfilename) + sizeof (".renamed")); - strcpy (newfilename, oldfilename); - strcat (newfilename, ".renamed"); - if (rename (oldfilename, newfilename)) - { - perror ("rename"); - exit (1); - } - - printf( "Loading shared object neededobj6.so\n"); - obj = dlopen( "neededobj6.so", RTLD_LAZY); - if (obj == NULL) - printf ("%s\n", dlerror ()); - else - { - printf ("neededobj6.so should fail to load\n"); - exit (1); - } - - printf( "Loading shared object neededobj1.so\n"); - obj = dlopen( "neededobj1.so", RTLD_LAZY); - if (obj == NULL) - { - printf ("%s\n", dlerror ()); - exit (1); - } - errors += check_loaded_objects (loaded); - f = dlsym (obj, "c_function"); - if (f == NULL) - { - printf ("%s\n", dlerror ()); - exit (1); - } - f (); - - printf ("Restore neededobj5.so\n"); - if (rename (newfilename, oldfilename)) - { - perror ("rename"); - exit (1); - } - - if (errors != 0) - printf ("%d errors found\n", errors); - return errors; -} diff --git a/elf/next.c b/elf/next.c deleted file mode 100644 index a0d532b8c3..0000000000 --- a/elf/next.c +++ /dev/null @@ -1,43 +0,0 @@ -#include <stdio.h> - - -extern int successful_rtld_next_test (void); -extern void *failing_rtld_next_use (void); - - -static int -do_test (void) -{ - int result; - void *addr; - - /* First try call a function which uses RTLD_NEXT and calls that - function. */ - result = successful_rtld_next_test (); - if (result == 42) - { - puts ("RTLD_NEXT seems to work for existing functions"); - result = 0; - } - else - { - printf ("Heh? `successful_rtld_next_test' returned %d\n", result); - result = 1; - } - - /* Next try a function which tries to get a function with RTLD_NEXT - but that fails. This dlsym() call should return a NULL pointer - and do nothing else. */ - addr = failing_rtld_next_use (); - if (addr == NULL) - puts ("dlsym returned NULL for non-existing function. Good"); - else - { - puts ("dlsym found something !?"); - result = 1; - } - - return result; -} - -#include <support/test-driver.c> diff --git a/elf/nextmod1.c b/elf/nextmod1.c deleted file mode 100644 index 56de3536a0..0000000000 --- a/elf/nextmod1.c +++ /dev/null @@ -1,30 +0,0 @@ -#include <dlfcn.h> - -extern int successful_rtld_next_test (void); -extern void *failing_rtld_next_use (void); - -int nextmod1_dummy_var; - -int -successful_rtld_next_test (void) -{ - int (*fp) (void); - - /* Get the next function... */ - fp = (int (*) (void)) dlsym (RTLD_NEXT, __FUNCTION__); - - /* ...and simply call it. */ - return fp (); -} - - -void * -failing_rtld_next_use (void) -{ - void *ret = dlsym (RTLD_NEXT, __FUNCTION__); - - /* Ensure we are not tail call optimized, because then RTLD_NEXT - might return this function. */ - ++nextmod1_dummy_var; - return ret; -} diff --git a/elf/nextmod2.c b/elf/nextmod2.c deleted file mode 100644 index b2c435f341..0000000000 --- a/elf/nextmod2.c +++ /dev/null @@ -1,10 +0,0 @@ -/* Very elaborated function. */ - -extern int successful_rtld_next_test (void); - - -int -successful_rtld_next_test (void) -{ - return 42; -} diff --git a/elf/nodel2mod1.c b/elf/nodel2mod1.c deleted file mode 100644 index acddc4cf8b..0000000000 --- a/elf/nodel2mod1.c +++ /dev/null @@ -1,19 +0,0 @@ -#include <stdlib.h> -void -foo (void) -{ - exit (0); -} - -void -__attribute__((destructor)) -bar (void) -{ - static int i; - foo (); - ++i; -} -void -baz (void) -{ -} diff --git a/elf/nodel2mod2.c b/elf/nodel2mod2.c deleted file mode 100644 index d0020240a8..0000000000 --- a/elf/nodel2mod2.c +++ /dev/null @@ -1,7 +0,0 @@ -void -__attribute__((constructor)) -xxx (void) -{ - extern void baz (void); - baz (); -} diff --git a/elf/nodel2mod3.c b/elf/nodel2mod3.c deleted file mode 100644 index 6d1a0d47b7..0000000000 --- a/elf/nodel2mod3.c +++ /dev/null @@ -1 +0,0 @@ -int x; diff --git a/elf/nodelete.c b/elf/nodelete.c deleted file mode 100644 index c8d71152f2..0000000000 --- a/elf/nodelete.c +++ /dev/null @@ -1,210 +0,0 @@ -#include <dlfcn.h> -#include <setjmp.h> -#include <signal.h> -#include <stdio.h> - - -static sigjmp_buf jmpbuf; - - -int fini_ran; - - -static void -__attribute__ ((noreturn)) -handler (int sig) -{ - siglongjmp (jmpbuf, 1); -} - - -static int -do_test (void) -{ - /* We are testing the two possibilities to mark an object as not deletable: - - marked on the linker commandline with `-z nodelete' - - with the RTLD_NODELETE flag at dlopen()-time. - - The test we are performing should be safe. We are loading the objects, - get the address of variables in the respective object, unload the object - and then try to read the variable. If the object is unloaded this - should lead to an segmentation fault. */ - int result = 0; - void *p; - struct sigaction sa; - - sa.sa_handler = handler; - sigfillset (&sa.sa_mask); - sa.sa_flags = SA_RESTART; - - if (sigaction (SIGSEGV, &sa, NULL) == -1) - printf ("cannot install signal handler: %m\n"); - - p = dlopen ("nodelmod1.so", RTLD_LAZY); - if (p == NULL) - { - printf ("failed to load \"nodelmod1.so\": %s\n", dlerror ()); - result = 1; - } - else - { - int *varp; - - puts ("succeeded loading \"nodelmod1.so\""); - - varp = dlsym (p, "var1"); - if (varp == NULL) - { - puts ("failed to get address of \"var1\" in \"nodelmod1.so\""); - result = 1; - } - else - { - *varp = 20000720; - - /* Now close the object. */ - fini_ran = 0; - if (dlclose (p) != 0) - { - puts ("failed to close \"nodelmod1.so\""); - result = 1; - } - else if (! sigsetjmp (jmpbuf, 1)) - { - /* Access the variable again. */ - if (*varp != 20000720) - { - puts ("\"var1\" value not correct"); - result = 1; - } - else if (fini_ran != 0) - { - puts ("destructor of \"nodelmod1.so\" ran"); - result = 1; - } - else - puts ("-z nodelete test succeeded"); - } - else - { - /* We caught an segmentation fault. */ - puts ("\"nodelmod1.so\" got deleted"); - result = 1; - } - } - } - - p = dlopen ("nodelmod2.so", RTLD_LAZY | RTLD_NODELETE); - if (p == NULL) - { - printf ("failed to load \"nodelmod2.so\": %s\n", dlerror ()); - result = 1; - } - else - { - int *varp; - - puts ("succeeded loading \"nodelmod2.so\""); - - varp = dlsym (p, "var2"); - if (varp == NULL) - { - puts ("failed to get address of \"var2\" in \"nodelmod2.so\""); - result = 1; - } - else - { - *varp = 42; - - /* Now close the object. */ - fini_ran = 0; - if (dlclose (p) != 0) - { - puts ("failed to close \"nodelmod2.so\""); - result = 1; - } - else if (! sigsetjmp (jmpbuf, 1)) - { - /* Access the variable again. */ - if (*varp != 42) - { - puts ("\"var2\" value not correct"); - result = 1; - } - else if (fini_ran != 0) - { - puts ("destructor of \"nodelmod2.so\" ran"); - result = 1; - } - else - puts ("RTLD_NODELETE test succeeded"); - } - else - { - /* We caught an segmentation fault. */ - puts ("\"nodelmod2.so\" got deleted"); - result = 1; - } - } - } - - p = dlopen ("nodelmod3.so", RTLD_LAZY); - if (p == NULL) - { - printf ("failed to load \"nodelmod3.so\": %s\n", dlerror ()); - result = 1; - } - else - { - int *(*fctp) (void); - - puts ("succeeded loading \"nodelmod3.so\""); - - fctp = dlsym (p, "addr"); - if (fctp == NULL) - { - puts ("failed to get address of \"addr\" in \"nodelmod3.so\""); - result = 1; - } - else - { - int *varp = fctp (); - - *varp = -1; - - /* Now close the object. */ - fini_ran = 0; - if (dlclose (p) != 0) - { - puts ("failed to close \"nodelmod3.so\""); - result = 1; - } - else if (! sigsetjmp (jmpbuf, 1)) - { - /* Access the variable again. */ - if (*varp != -1) - { - puts ("\"var_in_mod4\" value not correct"); - result = 1; - } - else if (fini_ran != 0) - { - puts ("destructor of \"nodelmod4.so\" ran"); - result = 1; - } - else - puts ("-z nodelete in dependency succeeded"); - } - else - { - /* We caught an segmentation fault. */ - puts ("\"nodelmod4.so\" got deleted"); - result = 1; - } - } - } - - return result; -} - -#include <support/test-driver.c> diff --git a/elf/nodelete2.c b/elf/nodelete2.c deleted file mode 100644 index b3d7e31a08..0000000000 --- a/elf/nodelete2.c +++ /dev/null @@ -1,16 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> -#include <dlfcn.h> - -int -main (void) -{ - void *handle = dlopen ("nodel2mod3.so", RTLD_LAZY); - if (handle == NULL) - { - printf ("%s\n", dlerror ()); - exit (1); - } - dlclose (handle); - exit (1); -} diff --git a/elf/nodelmod1.c b/elf/nodelmod1.c deleted file mode 100644 index fc24a7b172..0000000000 --- a/elf/nodelmod1.c +++ /dev/null @@ -1,9 +0,0 @@ -int var1 = 42; - -static void -__attribute__ ((__destructor__)) -destr (void) -{ - extern int fini_ran; - fini_ran = 1; -} diff --git a/elf/nodelmod2.c b/elf/nodelmod2.c deleted file mode 100644 index 6bd7108a13..0000000000 --- a/elf/nodelmod2.c +++ /dev/null @@ -1,9 +0,0 @@ -int var2 = 100; - -static void -__attribute__ ((__destructor__)) -destr (void) -{ - extern int fini_ran; - fini_ran = 1; -} diff --git a/elf/nodelmod3.c b/elf/nodelmod3.c deleted file mode 100644 index 817c94db6e..0000000000 --- a/elf/nodelmod3.c +++ /dev/null @@ -1,8 +0,0 @@ -extern int var_in_mod4; -extern int *addr (void); - -int * -addr (void) -{ - return &var_in_mod4; -} diff --git a/elf/nodelmod4.c b/elf/nodelmod4.c deleted file mode 100644 index 2cca43a6e8..0000000000 --- a/elf/nodelmod4.c +++ /dev/null @@ -1,9 +0,0 @@ -int var_in_mod4 = 99; - -static void -__attribute__ ((__destructor__)) -destr (void) -{ - extern int fini_ran; - fini_ran = 1; -} diff --git a/elf/nodlopen.c b/elf/nodlopen.c deleted file mode 100644 index 642bdb3011..0000000000 --- a/elf/nodlopen.c +++ /dev/null @@ -1,15 +0,0 @@ -#include <dlfcn.h> -#include <stdio.h> - -int -main (void) -{ - if (dlopen ("nodlopenmod.so", RTLD_LAZY) != NULL) - { - puts ("opening \"nodlopenmod.so\" succeeded, FAIL"); - return 1; - } - - puts ("opening \"nodlopenmod.so\" failed, OK"); - return 0; -} diff --git a/elf/nodlopen2.c b/elf/nodlopen2.c deleted file mode 100644 index a223f36834..0000000000 --- a/elf/nodlopen2.c +++ /dev/null @@ -1,15 +0,0 @@ -#include <dlfcn.h> -#include <stdio.h> - -int -main (void) -{ - if (dlopen ("nodlopenmod2.so", RTLD_LAZY) != NULL) - { - puts ("opening \"nodlopenmod2.so\" succeeded, FAIL"); - return 1; - } - - puts ("opening \"nodlopenmod2.so\" failed, OK"); - return 0; -} diff --git a/elf/nodlopenmod.c b/elf/nodlopenmod.c deleted file mode 100644 index 4bcf8c9786..0000000000 --- a/elf/nodlopenmod.c +++ /dev/null @@ -1 +0,0 @@ -int a = 42; diff --git a/elf/nodlopenmod2.c b/elf/nodlopenmod2.c deleted file mode 100644 index e72ae53e95..0000000000 --- a/elf/nodlopenmod2.c +++ /dev/null @@ -1,9 +0,0 @@ -extern int a; - -extern int foo (void); - -int -foo (void) -{ - return a; -} diff --git a/elf/noload.c b/elf/noload.c deleted file mode 100644 index bcc85efc27..0000000000 --- a/elf/noload.c +++ /dev/null @@ -1,81 +0,0 @@ -#include <dlfcn.h> -#include <stdio.h> -#include <mcheck.h> - -int -main (void) -{ - int result = 0; - void *p; - - mtrace (); - - /* First try to load an object which is a dependency. This should - succeed. */ - p = dlopen ("testobj1.so", RTLD_LAZY | RTLD_NOLOAD); - if (p == NULL) - { - printf ("cannot open \"testobj1.so\": %s\n", dlerror ()); - result = 1; - } - else - { - puts ("loading \"testobj1.so\" succeeded, OK"); - dlclose (p); - } - - /* Now try loading an object which is not already loaded. */ - if (dlopen ("testobj5.so", RTLD_LAZY | RTLD_NOLOAD) != NULL) - { - puts ("succeeded in loading \"testobj5.so\""); - result = 1; - } - else - { - /* Load the object and run the same test again. */ - puts ("\"testobj5.so\" wasn't loaded and RTLD_NOLOAD prevented it, OK"); - - p = dlopen ("testobj5.so", RTLD_LAZY); - - if (p == NULL) - { - printf ("cannot open \"testobj5.so\" without RTLD_NOLOAD: %s\n", - dlerror ()); - result = 1; - } - else - { - puts ("loading \"testobj5.so\" succeeded, OK"); - - void *q = dlopen ("testobj5.so", RTLD_LAZY | RTLD_NOLOAD); - if (q == NULL) - { - printf ("cannot open \"testobj5.so\": %s\n", dlerror ()); - result = 1; - } - else - { - puts ("loading \"testobj5.so\" with RTLD_NOLOAD succeeded, OK"); - dlclose (q); - } - - if (dlclose (p) != 0) - { - printf ("cannot close \"testobj5.so\": %s\n", dlerror ()); - result = 1; - } - else - puts ("closing \"testobj5.so\" succeeded, OK"); - } - } - - return result; -} - - -extern int foo (int a); -int -foo (int a) -{ - return 42 + a; -} diff --git a/elf/order.c b/elf/order.c deleted file mode 100644 index ca617cbc09..0000000000 --- a/elf/order.c +++ /dev/null @@ -1,25 +0,0 @@ -#include <unistd.h> - -void init (void) __attribute__ ((constructor)); -void -__attribute__ ((constructor)) -init (void) -{ - write (1, "4", 1); -} - -void fini (void) __attribute__ ((destructor)); -void -__attribute__ ((destructor)) -fini (void) -{ - write (1, "5", 1); -} - -extern int dep1 (void); - -int -main (void) -{ - return dep1 () != 42; -} diff --git a/elf/order2.c b/elf/order2.c deleted file mode 100644 index bcf266d5b1..0000000000 --- a/elf/order2.c +++ /dev/null @@ -1,45 +0,0 @@ -#include <dlfcn.h> -#include <stdio.h> - - -int call_puts; - -static int -do_test (void) -{ - call_puts = 1; - - void *h1 = dlopen ("$ORIGIN/order2mod1.so", RTLD_LAZY | RTLD_GLOBAL); - if (h1 == NULL) - { - puts ("cannot load order2mod1"); - return 1; - } - void *h2 = dlopen ("$ORIGIN/order2mod2.so", RTLD_LAZY); - if (h2 == NULL) - { - puts ("cannot load order2mod2"); - return 1; - } - if (dlclose (h1) != 0) - { - puts ("dlclose order2mod1 failed"); - return 1; - } - if (dlclose (h2) != 0) - { - puts ("dlclose order2mod2 failed"); - return 1; - } - return 0; -} - -#include <support/test-driver.c> - -static void -__attribute__ ((destructor)) -fini (void) -{ - if (call_puts) - puts ("5"); -} diff --git a/elf/order2mod1.c b/elf/order2mod1.c deleted file mode 100644 index b695db29b7..0000000000 --- a/elf/order2mod1.c +++ /dev/null @@ -1,8 +0,0 @@ -#include <stdio.h> - -static void -__attribute__ ((destructor)) -fini (void) -{ - putchar ('1'); -} diff --git a/elf/order2mod2.c b/elf/order2mod2.c deleted file mode 100644 index 026cd2acc4..0000000000 --- a/elf/order2mod2.c +++ /dev/null @@ -1,18 +0,0 @@ -#include <stdio.h> - -extern int foo (void); -extern int bar (void); - -void -__attribute__ ((constructor)) -init (void) -{ - (void) (foo () - bar ()); -} - -static void -__attribute__ ((destructor)) -fini (void) -{ - putchar ('2'); -} diff --git a/elf/order2mod3.c b/elf/order2mod3.c deleted file mode 100644 index 7913a79925..0000000000 --- a/elf/order2mod3.c +++ /dev/null @@ -1,14 +0,0 @@ -#include <stdio.h> - -int -bar (void) -{ - return 1; -} - -static void -__attribute__ ((destructor)) -fini (void) -{ - putchar ('4'); -} diff --git a/elf/order2mod4.c b/elf/order2mod4.c deleted file mode 100644 index 4f2026f041..0000000000 --- a/elf/order2mod4.c +++ /dev/null @@ -1,16 +0,0 @@ -#include <stdio.h> - -extern int bar (void); - -int -foo (void) -{ - return 42 + bar (); -} - -static void -__attribute__ ((destructor)) -fini (void) -{ - putchar ('3'); -} diff --git a/elf/origtest.c b/elf/origtest.c deleted file mode 100644 index 1cacabcc39..0000000000 --- a/elf/origtest.c +++ /dev/null @@ -1,39 +0,0 @@ -#include <dlfcn.h> -#include <error.h> -#include <stdio.h> -#include <stdlib.h> - -int -main (void) -{ - void *h; - int (*fp) (int); - int res; - - h = dlopen ("${ORIGIN}/testobj1.so", RTLD_LAZY); - if (h == NULL) - error (EXIT_FAILURE, 0, "while loading `%s': %s", "testobj1.so", - dlerror ()); - - fp = dlsym (h, "obj1func1"); - if (fp == NULL) - error (EXIT_FAILURE, 0, "getting `obj1func1' in `%s': %s", - "testobj1.so", dlerror ()); - - res = fp (10); - printf ("fp(10) = %d\n", res); - - if (dlclose (h) != 0) - error (EXIT_FAILURE, 0, "while close `%s': %s", - "testobj1.so", dlerror ()); - - return res != 42; -} - - -extern int foo (int a); -int -foo (int a) -{ - return a + 10; -} diff --git a/elf/pathoptobj.c b/elf/pathoptobj.c deleted file mode 100644 index a452c2d7d4..0000000000 --- a/elf/pathoptobj.c +++ /dev/null @@ -1,8 +0,0 @@ -extern int in_renamed (int); - - -int -in_renamed (int a) -{ - return a - 10; -} diff --git a/elf/pldd-xx.c b/elf/pldd-xx.c deleted file mode 100644 index 5ce0bce4c9..0000000000 --- a/elf/pldd-xx.c +++ /dev/null @@ -1,251 +0,0 @@ -/* Copyright (C) 2011-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Ulrich Drepper <drepper@gmail.com>, 2011. - - 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/>. */ - -#define E(name) E_(name, CLASS) -#define E_(name, cl) E__(name, cl) -#define E__(name, cl) name##cl -#define EW(type) EW_(Elf, CLASS, type) -#define EW_(e, w, t) EW__(e, w, _##t) -#define EW__(e, w, t) e##w##t - -#define pldd_assert(name, exp) \ - typedef int __assert_##name[((exp) != 0) - 1] - - -struct E(link_map) -{ - EW(Addr) l_addr; - EW(Addr) l_name; - EW(Addr) l_ld; - EW(Addr) l_next; - EW(Addr) l_prev; - EW(Addr) l_real; - Lmid_t l_ns; - EW(Addr) l_libname; -}; -#if CLASS == __ELF_NATIVE_CLASS -pldd_assert (l_addr, (offsetof (struct link_map, l_addr) - == offsetof (struct E(link_map), l_addr))); -pldd_assert (l_name, (offsetof (struct link_map, l_name) - == offsetof (struct E(link_map), l_name))); -pldd_assert (l_next, (offsetof (struct link_map, l_next) - == offsetof (struct E(link_map), l_next))); -#endif - - -struct E(libname_list) -{ - EW(Addr) name; - EW(Addr) next; -}; -#if CLASS == __ELF_NATIVE_CLASS -pldd_assert (name, (offsetof (struct libname_list, name) - == offsetof (struct E(libname_list), name))); -pldd_assert (next, (offsetof (struct libname_list, next) - == offsetof (struct E(libname_list), next))); -#endif - -struct E(r_debug) -{ - int r_version; -#if CLASS == 64 - int pad; -#endif - EW(Addr) r_map; -}; -#if CLASS == __ELF_NATIVE_CLASS -pldd_assert (r_version, (offsetof (struct r_debug, r_version) - == offsetof (struct E(r_debug), r_version))); -pldd_assert (r_map, (offsetof (struct r_debug, r_map) - == offsetof (struct E(r_debug), r_map))); -#endif - - -static int - -E(find_maps) (pid_t pid, void *auxv, size_t auxv_size) -{ - EW(Addr) phdr = 0; - unsigned int phnum = 0; - unsigned int phent = 0; - - EW(auxv_t) *auxvXX = (EW(auxv_t) *) auxv; - for (int i = 0; i < auxv_size / sizeof (EW(auxv_t)); ++i) - switch (auxvXX[i].a_type) - { - case AT_PHDR: - phdr = auxvXX[i].a_un.a_val; - break; - case AT_PHNUM: - phnum = auxvXX[i].a_un.a_val; - break; - case AT_PHENT: - phent = auxvXX[i].a_un.a_val; - break; - default: - break; - } - - if (phdr == 0 || phnum == 0 || phent == 0) - error (EXIT_FAILURE, 0, gettext ("cannot find program header of process")); - - EW(Phdr) *p = alloca (phnum * phent); - if (pread64 (memfd, p, phnum * phent, phdr) != phnum * phent) - { - error (0, 0, gettext ("cannot read program header")); - return EXIT_FAILURE; - } - - /* Determine the load offset. We need this for interpreting the - other program header entries so we do this in a separate loop. - Fortunately it is the first time unless someone does something - stupid when linking the application. */ - EW(Addr) offset = 0; - for (unsigned int i = 0; i < phnum; ++i) - if (p[i].p_type == PT_PHDR) - { - offset = phdr - p[i].p_vaddr; - break; - } - - EW(Addr) list = 0; - char *interp = NULL; - for (unsigned int i = 0; i < phnum; ++i) - if (p[i].p_type == PT_DYNAMIC) - { - EW(Dyn) *dyn = xmalloc (p[i].p_filesz); - if (pread64 (memfd, dyn, p[i].p_filesz, offset + p[i].p_vaddr) - != p[i].p_filesz) - { - error (0, 0, gettext ("cannot read dynamic section")); - return EXIT_FAILURE; - } - - /* Search for the DT_DEBUG entry. */ - for (unsigned int j = 0; j < p[i].p_filesz / sizeof (EW(Dyn)); ++j) - if (dyn[j].d_tag == DT_DEBUG && dyn[j].d_un.d_ptr != 0) - { - struct E(r_debug) r; - if (pread64 (memfd, &r, sizeof (r), dyn[j].d_un.d_ptr) - != sizeof (r)) - { - error (0, 0, gettext ("cannot read r_debug")); - return EXIT_FAILURE; - } - - if (r.r_map != 0) - { - list = r.r_map; - break; - } - } - - free (dyn); - break; - } - else if (p[i].p_type == PT_INTERP) - { - interp = alloca (p[i].p_filesz); - if (pread64 (memfd, interp, p[i].p_filesz, offset + p[i].p_vaddr) - != p[i].p_filesz) - { - error (0, 0, gettext ("cannot read program interpreter")); - return EXIT_FAILURE; - } - } - - if (list == 0) - { - if (interp == NULL) - { - // XXX check whether the executable itself is the loader - return EXIT_FAILURE; - } - - // XXX perhaps try finding ld.so and _r_debug in it - - return EXIT_FAILURE; - } - - /* Print the PID and program name first. */ - printf ("%lu:\t%s\n", (unsigned long int) pid, exe); - - /* Iterate over the list of objects and print the information. */ - 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")); - status = EXIT_FAILURE; - goto out; - } - - EW(Addr) name_offset = m.l_name; - again: - while (1) - { - ssize_t n = pread64 (memfd, tmpbuf.data, tmpbuf.length, name_offset); - if (n == -1) - { - error (0, 0, gettext ("cannot read object name")); - status = EXIT_FAILURE; - goto out; - } - - if (memchr (tmpbuf.data, '\0', n) != NULL) - break; - - if (!scratch_buffer_grow (&tmpbuf)) - { - error (0, 0, gettext ("cannot allocate buffer for object name")); - status = EXIT_FAILURE; - goto out; - } - } - - if (((char *)tmpbuf.data)[0] == '\0' && name_offset == m.l_name - && m.l_libname != 0) - { - /* Try the l_libname element. */ - struct E(libname_list) ln; - if (pread64 (memfd, &ln, sizeof (ln), m.l_libname) == sizeof (ln)) - { - name_offset = ln.name; - goto again; - } - } - - /* Skip over the executable. */ - if (((char *)tmpbuf.data)[0] != '\0') - printf ("%s\n", (char *)tmpbuf.data); - - list = m.l_next; - } - while (list != 0); - - out: - scratch_buffer_free (&tmpbuf); - return status; -} - - -#undef CLASS diff --git a/elf/pldd.c b/elf/pldd.c deleted file mode 100644 index ddfa88d63b..0000000000 --- a/elf/pldd.c +++ /dev/null @@ -1,344 +0,0 @@ -/* List dynamic shared objects linked into given process. - Copyright (C) 2011-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Ulrich Drepper <drepper@gmail.com>, 2011. - - 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 <alloca.h> -#include <argp.h> -#include <assert.h> -#include <dirent.h> -#include <elf.h> -#include <errno.h> -#include <error.h> -#include <fcntl.h> -#include <libintl.h> -#include <link.h> -#include <stddef.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#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> - -/* Global variables. */ -extern char *program_invocation_short_name; -#define PACKAGE _libc_intl_domainname - -/* External functions. */ -#include <programs/xmalloc.h> - -/* Name and version of program. */ -static void print_version (FILE *stream, struct argp_state *state); -void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version; - -/* Function to print some extra text in the help message. */ -static char *more_help (int key, const char *text, void *input); - -/* Definitions of arguments for argp functions. */ -static const struct argp_option options[] = -{ - { NULL, 0, NULL, 0, NULL } -}; - -/* Short description of program. */ -static const char doc[] = N_("\ -List dynamic shared objects loaded into process."); - -/* Strings for arguments in help texts. */ -static const char args_doc[] = N_("PID"); - -/* Prototype for option handler. */ -static error_t parse_opt (int key, char *arg, struct argp_state *state); - -/* Data structure to communicate with argp functions. */ -static struct argp argp = -{ - options, parse_opt, args_doc, doc, NULL, more_help, NULL -}; - -// File descriptor of /proc/*/mem file. -static int memfd; - -/* Name of the executable */ -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 -main (int argc, char *argv[]) -{ - /* Parse and process arguments. */ - int remaining; - argp_parse (&argp, argc, argv, 0, &remaining, NULL); - - if (remaining != argc - 1) - { - fprintf (stderr, - gettext ("Exactly one parameter with process ID required.\n")); - argp_help (&argp, stderr, ARGP_HELP_SEE, program_invocation_short_name); - return 1; - } - - assert (sizeof (pid_t) == sizeof (int) - || sizeof (pid_t) == sizeof (long int)); - char *endp; - errno = 0; - long int pid = strtol (argv[remaining], &endp, 10); - if (pid < 0 || (pid == ULONG_MAX && errno == ERANGE) || *endp != '\0' - || (sizeof (pid_t) < sizeof (pid) && pid > INT_MAX)) - error (EXIT_FAILURE, 0, gettext ("invalid process ID '%s'"), - argv[remaining]); - - /* Determine the program name. */ - char buf[7 + 3 * sizeof (pid)]; - snprintf (buf, sizeof (buf), "/proc/%lu", pid); - int dfd = open (buf, O_RDONLY | O_DIRECTORY); - if (dfd == -1) - error (EXIT_FAILURE, errno, gettext ("cannot open %s"), buf); - - struct scratch_buffer exebuf; - scratch_buffer_init (&exebuf); - ssize_t nexe; - 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 = exebuf.data; - exe[nexe] = '\0'; - } - - /* Stop all threads since otherwise the list of loaded modules might - change while we are reading it. */ - struct thread_list - { - pid_t tid; - struct thread_list *next; - } *thread_list = NULL; - - int taskfd = openat (dfd, "task", O_RDONLY | O_DIRECTORY | O_CLOEXEC); - if (taskfd == 1) - error (EXIT_FAILURE, errno, gettext ("cannot open %s/task"), buf); - DIR *dir = fdopendir (taskfd); - if (dir == NULL) - error (EXIT_FAILURE, errno, gettext ("cannot prepare reading %s/task"), - buf); - - struct dirent64 *d; - while ((d = readdir64 (dir)) != NULL) - { - if (! isdigit (d->d_name[0])) - continue; - - errno = 0; - long int tid = strtol (d->d_name, &endp, 10); - if (tid < 0 || (tid == ULONG_MAX && errno == ERANGE) || *endp != '\0' - || (sizeof (pid_t) < sizeof (pid) && tid > INT_MAX)) - error (EXIT_FAILURE, 0, gettext ("invalid thread ID '%s'"), - d->d_name); - - if (ptrace (PTRACE_ATTACH, tid, NULL, NULL) != 0) - { - /* There might be a race between reading the directory and - threads terminating. Ignore errors attaching to unknown - threads unless this is the main thread. */ - if (errno == ESRCH && tid != pid) - continue; - - error (EXIT_FAILURE, errno, gettext ("cannot attach to process %lu"), - tid); - } - - wait_for_ptrace_stop (tid); - - struct thread_list *newp = alloca (sizeof (*newp)); - newp->tid = tid; - newp->next = thread_list; - thread_list = newp; - } - - closedir (dir); - - int status = get_process_info (dfd, pid); - - assert (thread_list != NULL); - do - { - ptrace (PTRACE_DETACH, thread_list->tid, NULL, NULL); - thread_list = thread_list->next; - } - while (thread_list != NULL); - - close (dfd); - - return status; -} - - -/* 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) -{ - switch (key) - { - default: - return ARGP_ERR_UNKNOWN; - } - return 0; -} - - -/* Print bug-reporting information in the help message. */ -static char * -more_help (int key, const char *text, void *input) -{ - char *tp = NULL; - switch (key) - { - case ARGP_KEY_HELP_EXTRA: - /* We print some extra information. */ - if (asprintf (&tp, gettext ("\ -For bug reporting instructions, please see:\n\ -%s.\n"), REPORT_BUGS_TO) < 0) - return NULL; - return tp; - default: - break; - } - return (char *) text; -} - -/* Print the version information. */ -static void -print_version (FILE *stream, struct argp_state *state) -{ - fprintf (stream, "pldd %s%s\n", PKGVERSION, VERSION); - fprintf (stream, gettext ("\ -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\ -"), "2017"); - fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper"); -} - - -#define CLASS 32 -#include "pldd-xx.c" -#define CLASS 64 -#include "pldd-xx.c" - - -static int -get_process_info (int dfd, long int pid) -{ - memfd = openat (dfd, "mem", O_RDONLY); - if (memfd == -1) - goto no_info; - - int fd = openat (dfd, "exe", O_RDONLY); - if (fd == -1) - { - no_info: - error (0, errno, gettext ("cannot get information about process %lu"), - pid); - return EXIT_FAILURE; - } - - char e_ident[EI_NIDENT]; - if (read (fd, e_ident, EI_NIDENT) != EI_NIDENT) - goto no_info; - - close (fd); - - if (memcmp (e_ident, ELFMAG, SELFMAG) != 0) - { - error (0, 0, gettext ("process %lu is no ELF program"), pid); - return EXIT_FAILURE; - } - - fd = openat (dfd, "auxv", O_RDONLY); - if (fd == -1) - goto no_info; - - size_t auxv_size = 0; - void *auxv = NULL; - while (1) - { - auxv_size += 512; - auxv = xrealloc (auxv, auxv_size); - - ssize_t n = pread (fd, auxv, auxv_size, 0); - if (n < 0) - goto no_info; - if (n < auxv_size) - { - auxv_size = n; - break; - } - } - - close (fd); - - int retval; - if (e_ident[EI_CLASS] == ELFCLASS32) - retval = find_maps32 (pid, auxv, auxv_size); - else - retval = find_maps64 (pid, auxv, auxv_size); - - free (auxv); - close (memfd); - - return retval; -} diff --git a/elf/preloadtest.c b/elf/preloadtest.c deleted file mode 100644 index 7ea10b9b5b..0000000000 --- a/elf/preloadtest.c +++ /dev/null @@ -1,19 +0,0 @@ -#include <stdio.h> - -#include "testobj.h" - -int -main (void) -{ - int res = preload (42); - - printf ("preload (42) = %d, %s\n", res, res == 92 ? "ok" : "wrong"); - - return res != 92; -} - -int -foo (int a) -{ - return a; -} diff --git a/elf/readelflib.c b/elf/readelflib.c deleted file mode 100644 index 9ad56dcc34..0000000000 --- a/elf/readelflib.c +++ /dev/null @@ -1,234 +0,0 @@ -/* Copyright (C) 1999-2017 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. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -/* This code is a heavily simplified version of the readelf program - that's part of the current binutils development version. For architectures - which need to handle both 32bit and 64bit ELF libraries, this file is - included twice for each arch size. */ - -/* check_ptr checks that a pointer is in the mmaped file and doesn't - point outside it. */ -#undef check_ptr -#define check_ptr(ptr) \ -do \ - { \ - if ((void *)(ptr) < file_contents \ - || (void *)(ptr) > (file_contents+file_length)) \ - { \ - error (0, 0, _("file %s is truncated\n"), file_name); \ - return 1; \ - } \ - } \ - while (0); - -/* Returns 0 if everything is ok, != 0 in case of error. */ -int -process_elf_file (const char *file_name, const char *lib, int *flag, - unsigned int *osversion, char **soname, void *file_contents, - size_t file_length) -{ - int i; - unsigned int j; - ElfW(Addr) loadaddr; - unsigned int dynamic_addr; - size_t dynamic_size; - char *program_interpreter; - - ElfW(Ehdr) *elf_header; - ElfW(Phdr) *elf_pheader, *segment; - ElfW(Dyn) *dynamic_segment, *dyn_entry; - char *dynamic_strings; - - elf_header = (ElfW(Ehdr) *) file_contents; - *osversion = 0; - - if (elf_header->e_ident [EI_CLASS] != ElfW (CLASS)) - { - if (opt_verbose) - { - if (elf_header->e_ident [EI_CLASS] == ELFCLASS32) - error (0, 0, _("%s is a 32 bit ELF file.\n"), file_name); - else if (elf_header->e_ident [EI_CLASS] == ELFCLASS64) - error (0, 0, _("%s is a 64 bit ELF file.\n"), file_name); - else - error (0, 0, _("Unknown ELFCLASS in file %s.\n"), file_name); - } - return 1; - } - - if (elf_header->e_type != ET_DYN) - { - error (0, 0, _("%s is not a shared object file (Type: %d).\n"), file_name, - elf_header->e_type); - return 1; - } - - /* Get information from elf program header. */ - elf_pheader = (ElfW(Phdr) *) (elf_header->e_phoff + file_contents); - check_ptr (elf_pheader); - - /* The library is an elf library, now search for soname and - libc5/libc6. */ - *flag = FLAG_ELF; - - loadaddr = -1; - dynamic_addr = 0; - dynamic_size = 0; - program_interpreter = NULL; - for (i = 0, segment = elf_pheader; - i < elf_header->e_phnum; i++, segment++) - { - check_ptr (segment); - - switch (segment->p_type) - { - case PT_LOAD: - if (loadaddr == (ElfW(Addr)) -1) - loadaddr = segment->p_vaddr - segment->p_offset; - break; - - case PT_DYNAMIC: - if (dynamic_addr) - error (0, 0, _("more than one dynamic segment\n")); - - dynamic_addr = segment->p_offset; - dynamic_size = segment->p_filesz; - break; - - case PT_INTERP: - program_interpreter = (char *) (file_contents + segment->p_offset); - check_ptr (program_interpreter); - - /* Check if this is enough to classify the binary. */ - for (j = 0; j < sizeof (interpreters) / sizeof (interpreters [0]); - ++j) - if (strcmp (program_interpreter, interpreters[j].soname) == 0) - { - *flag = interpreters[j].flag; - break; - } - break; - - case PT_NOTE: - if (!*osversion && segment->p_filesz >= 32 && segment->p_align >= 4) - { - ElfW(Word) *abi_note = (ElfW(Word) *) (file_contents - + segment->p_offset); - ElfW(Addr) size = segment->p_filesz; - - while (abi_note [0] != 4 || abi_note [1] != 16 - || abi_note [2] != 1 - || memcmp (abi_note + 3, "GNU", 4) != 0) - { -#define ROUND(len) (((len) + sizeof (ElfW(Word)) - 1) & -sizeof (ElfW(Word))) - ElfW(Addr) note_size = 3 * sizeof (ElfW(Word)) - + ROUND (abi_note[0]) - + ROUND (abi_note[1]); - - if (size - 32 < note_size || note_size == 0) - { - size = 0; - break; - } - size -= note_size; - abi_note = (void *) abi_note + note_size; - } - - if (size == 0) - break; - - *osversion = (abi_note [4] << 24) | - ((abi_note [5] & 0xff) << 16) | - ((abi_note [6] & 0xff) << 8) | - (abi_note [7] & 0xff); - } - break; - - default: - break; - } - - } - if (loadaddr == (ElfW(Addr)) -1) - { - /* Very strange. */ - loadaddr = 0; - } - - /* Now we can read the dynamic sections. */ - if (dynamic_size == 0) - return 1; - - dynamic_segment = (ElfW(Dyn) *) (file_contents + dynamic_addr); - check_ptr (dynamic_segment); - - /* Find the string table. */ - dynamic_strings = NULL; - for (dyn_entry = dynamic_segment; dyn_entry->d_tag != DT_NULL; - ++dyn_entry) - { - check_ptr (dyn_entry); - if (dyn_entry->d_tag == DT_STRTAB) - { - dynamic_strings = (char *) (file_contents + dyn_entry->d_un.d_val - loadaddr); - check_ptr (dynamic_strings); - break; - } - } - - if (dynamic_strings == NULL) - return 1; - - /* Now read the DT_NEEDED and DT_SONAME entries. */ - for (dyn_entry = dynamic_segment; dyn_entry->d_tag != DT_NULL; - ++dyn_entry) - { - if (dyn_entry->d_tag == DT_NEEDED || dyn_entry->d_tag == DT_SONAME) - { - char *name = dynamic_strings + dyn_entry->d_un.d_val; - check_ptr (name); - - if (dyn_entry->d_tag == DT_NEEDED) - { - - if (*flag == FLAG_ELF) - { - /* Check if this is enough to classify the binary. */ - for (j = 0; - j < sizeof (known_libs) / sizeof (known_libs [0]); - ++j) - if (strcmp (name, known_libs [j].soname) == 0) - { - *flag = known_libs [j].flag; - break; - } - } - } - - else if (dyn_entry->d_tag == DT_SONAME) - *soname = xstrdup (name); - - /* Do we have everything we need? */ - if (*soname && *flag != FLAG_ELF) - return 0; - } - } - - return 0; -} diff --git a/elf/readlib.c b/elf/readlib.c deleted file mode 100644 index d278a189b2..0000000000 --- a/elf/readlib.c +++ /dev/null @@ -1,212 +0,0 @@ -/* Copyright (C) 1999-2017 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. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, see <http://www.gnu.org/licenses/>. */ - -/* The code in this file and in readelflib is a heavily simplified - version of the readelf program that's part of the current binutils - development version. Besides the simplification, it has also been - modified to read some other file formats. */ - -#include <a.out.h> -#include <elf.h> -#include <error.h> -#include <libintl.h> -#include <link.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <sys/mman.h> -#include <sys/param.h> -#include <sys/stat.h> -#include <gnu/lib-names.h> - -#include <ldconfig.h> - -#define Elf32_CLASS ELFCLASS32 -#define Elf64_CLASS ELFCLASS64 - -struct known_names -{ - const char *soname; - int flag; -}; - -static struct known_names interpreters[] = -{ - { "/lib/" LD_SO, FLAG_ELF_LIBC6 }, -#ifdef SYSDEP_KNOWN_INTERPRETER_NAMES - SYSDEP_KNOWN_INTERPRETER_NAMES -#endif -}; - -static struct known_names known_libs[] = -{ - { LIBC_SO, FLAG_ELF_LIBC6 }, - { LIBM_SO, FLAG_ELF_LIBC6 }, -#ifdef SYSDEP_KNOWN_LIBRARY_NAMES - SYSDEP_KNOWN_LIBRARY_NAMES -#endif -}; - - -/* 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 -process_file (const char *real_file_name, const char *file_name, - const char *lib, int *flag, unsigned int *osversion, - char **soname, int is_link, struct stat64 *stat_buf) -{ - FILE *file; - struct stat64 statbuf; - void *file_contents; - int ret; - ElfW(Ehdr) *elf_header; - struct exec *aout_header; - - ret = 0; - *flag = FLAG_ANY; - *soname = NULL; - - file = fopen (real_file_name, "rb"); - if (file == NULL) - { - /* No error for stale symlink. */ - if (is_link && strstr (file_name, ".so") != NULL) - return 1; - error (0, 0, _("Input file %s not found.\n"), file_name); - return 1; - } - - if (fstat64 (fileno (file), &statbuf) < 0) - { - error (0, 0, _("Cannot fstat file %s.\n"), file_name); - fclose (file); - return 1; - } - - /* Check that the file is large enough so that we can access the - information. We're only checking the size of the headers here. */ - if ((size_t) statbuf.st_size < sizeof (struct exec) - || (size_t) statbuf.st_size < sizeof (ElfW(Ehdr))) - { - if (statbuf.st_size == 0) - error (0, 0, _("File %s is empty, not checked."), file_name); - else - { - char buf[SELFMAG]; - size_t n = MIN (statbuf.st_size, SELFMAG); - if (fread (buf, n, 1, file) == 1 && memcmp (buf, ELFMAG, n) == 0) - error (0, 0, _("File %s is too small, not checked."), file_name); - } - fclose (file); - return 1; - } - - file_contents = mmap (0, statbuf.st_size, PROT_READ, MAP_SHARED, - fileno (file), 0); - if (file_contents == MAP_FAILED) - { - error (0, 0, _("Cannot mmap file %s.\n"), file_name); - fclose (file); - return 1; - } - - /* First check if this is an aout file. */ - aout_header = (struct exec *) file_contents; - if (N_MAGIC (*aout_header) == ZMAGIC -#ifdef QMAGIC /* Linuxism. */ - || N_MAGIC (*aout_header) == QMAGIC -#endif - ) - { - /* Aout files don't have a soname, just return the name - including the major number. */ - char *copy, *major, *dot; - copy = xstrdup (lib); - major = strstr (copy, ".so."); - if (major) - { - dot = strstr (major + 4, "."); - if (dot) - *dot = '\0'; - } - *soname = copy; - *flag = FLAG_LIBC4; - goto done; - } - - elf_header = (ElfW(Ehdr) *) file_contents; - if (memcmp (elf_header->e_ident, ELFMAG, SELFMAG) != 0) - { - /* The file is neither ELF nor aout. Check if it's a linker - script, like libc.so - otherwise complain. Only search the - 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 - && !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; - } - /* Libraries have to be shared object files. */ - else if (elf_header->e_type != ET_DYN) - ret = 1; - else if (process_elf_file (file_name, lib, flag, osversion, soname, - file_contents, statbuf.st_size)) - ret = 1; - - done: - /* Clean up allocated memory and resources. */ - munmap (file_contents, statbuf.st_size); - fclose (file); - - *stat_buf = statbuf; - return ret; -} - -/* Returns made up soname if lib doesn't have explicit DT_SONAME. */ - -char * -implicit_soname (const char *lib, int flag) -{ - char *soname = xstrdup (lib); - - if ((flag & FLAG_TYPE_MASK) != FLAG_LIBC4) - return soname; - - /* Aout files don't have a soname, just return the name - including the major number. */ - char *major = strstr (soname, ".so."); - if (major) - { - char *dot = strstr (major + 4, "."); - if (dot) - *dot = '\0'; - } - return soname; -} - -/* Get architecture specific version of process_elf_file. */ -#include <readelflib.c> diff --git a/elf/reldep.c b/elf/reldep.c deleted file mode 100644 index adabc0d5d5..0000000000 --- a/elf/reldep.c +++ /dev/null @@ -1,111 +0,0 @@ -#include <dlfcn.h> -#include <mcheck.h> -#include <stdio.h> -#include <stdlib.h> - -int -main (void) -{ - void *h1; - void *h2; - int (*fp) (void); - int *vp; - - mtrace (); - - /* Open the two objects. */ - h1 = dlopen ("reldepmod1.so", RTLD_LAZY | RTLD_GLOBAL); - if (h1 == NULL) - { - printf ("cannot open reldepmod1.so: %s\n", dlerror ()); - exit (1); - } - h2 = dlopen ("reldepmod2.so", RTLD_LAZY); - if (h2 == NULL) - { - printf ("cannot open reldepmod2.so: %s\n", dlerror ()); - exit (1); - } - - /* Get the address of the variable in reldepmod1.so. */ - vp = dlsym (h1, "some_var"); - if (vp == NULL) - { - printf ("cannot get address of \"some_var\": %s\n", dlerror ()); - exit (1); - } - - *vp = 42; - - /* Get the function `call_me' in the second object. This has a - dependency which is resolved by a definition in reldepmod1.so. */ - fp = dlsym (h2, "call_me"); - if (fp == NULL) - { - printf ("cannot get address of \"call_me\": %s\n", dlerror ()); - exit (1); - } - - /* Call the function. */ - if (fp () != 0) - { - puts ("function \"call_me\" returned wrong result"); - exit (1); - } - - /* Now close the first object. If must still be around since we have - an implicit dependency. */ - if (dlclose (h1) != 0) - { - printf ("closing h1 failed: %s\n", dlerror ()); - exit (1); - } - - /* Try calling the function again. This will fail if the first object - got unloaded. */ - if (fp () != 0) - { - puts ("second call of function \"call_me\" returned wrong result"); - exit (1); - } - - /* Now close the second file as well. */ - if (dlclose (h2) != 0) - { - printf ("closing h2 failed: %s\n", dlerror ()); - exit (1); - } - - /* Finally, open the first object again. */ - h1 = dlopen ("reldepmod1.so", RTLD_LAZY | RTLD_GLOBAL); - if (h1 == NULL) - { - printf ("cannot open reldepmod1.so the second time: %s\n", dlerror ()); - exit (1); - } - - /* And get the variable address again. */ - vp = dlsym (h1, "some_var"); - if (vp == NULL) - { - printf ("cannot get address of \"some_var\" the second time: %s\n", - dlerror ()); - exit (1); - } - - /* The variable now must have its originial value. */ - if (*vp != 0) - { - puts ("variable \"some_var\" not reset"); - exit (1); - } - - /* Close the first object again, we are done. */ - if (dlclose (h1) != 0) - { - printf ("closing h1 failed: %s\n", dlerror ()); - exit (1); - } - - return 0; -} diff --git a/elf/reldep2.c b/elf/reldep2.c deleted file mode 100644 index ba5ab222f9..0000000000 --- a/elf/reldep2.c +++ /dev/null @@ -1,101 +0,0 @@ -#include <dlfcn.h> -#include <mcheck.h> -#include <stdio.h> -#include <stdlib.h> - -int -main (void) -{ - void *h1; - void *h2; - int (*fp) (void); - int *vp; - - mtrace (); - - /* Open the two objects. */ - h1 = dlopen ("reldepmod1.so", RTLD_LAZY | RTLD_GLOBAL); - if (h1 == NULL) - { - printf ("cannot open reldepmod1.so: %s\n", dlerror ()); - exit (1); - } - h2 = dlopen ("reldepmod3.so", RTLD_LAZY); - if (h2 == NULL) - { - printf ("cannot open reldepmod3.so: %s\n", dlerror ()); - exit (1); - } - - /* Get the address of the variable in reldepmod1.so. */ - vp = dlsym (h1, "some_var"); - if (vp == NULL) - { - printf ("cannot get address of \"some_var\": %s\n", dlerror ()); - exit (1); - } - - *vp = 42; - - /* Get the function `call_me' in the second object. This has a - dependency which is resolved by a definition in reldepmod1.so. */ - fp = dlsym (h2, "call_me"); - if (fp == NULL) - { - printf ("cannot get address of \"call_me\": %s\n", dlerror ()); - exit (1); - } - - /* Call the function. */ - if (fp () != 0) - { - puts ("function \"call_me\" returned wrong result"); - exit (1); - } - - /* Now close the first object. It must still be around since we have - an implicit dependency. */ - if (dlclose (h1) != 0) - { - printf ("closing h1 failed: %s\n", dlerror ()); - exit (1); - } - - /* Open the first object again. */ - h1 = dlopen ("reldepmod1.so", RTLD_LAZY | RTLD_GLOBAL); - if (h1 == NULL) - { - printf ("cannot open reldepmod1.so the second time: %s\n", dlerror ()); - exit (1); - } - - /* Get the variable address again. */ - vp = dlsym (h1, "some_var"); - if (vp == NULL) - { - printf ("cannot get address of \"some_var\" the second time: %s\n", - dlerror ()); - exit (1); - } - - /* The variable now must have its originial value. */ - if (*vp != 42) - { - puts ("variable \"some_var\" reset"); - exit (1); - } - - /* Close the first object again, we are done. */ - if (dlclose (h1) != 0) - { - printf ("closing h1 failed: %s\n", dlerror ()); - exit (1); - } - if (dlclose (h2) != 0) - { - printf ("closing h2 failed: %s\n", dlerror ()); - exit (1); - } - - return 0; -} diff --git a/elf/reldep3.c b/elf/reldep3.c deleted file mode 100644 index 05013d3509..0000000000 --- a/elf/reldep3.c +++ /dev/null @@ -1,101 +0,0 @@ -#include <dlfcn.h> -#include <mcheck.h> -#include <stdio.h> -#include <stdlib.h> - -int -main (void) -{ - void *h1; - void *h2; - int (*fp) (void); - int *vp; - - mtrace (); - - /* Open the two objects. */ - h1 = dlopen ("reldepmod1.so", RTLD_LAZY | RTLD_GLOBAL); - if (h1 == NULL) - { - printf ("cannot open reldepmod1.so: %s\n", dlerror ()); - exit (1); - } - h2 = dlopen ("reldepmod4.so", RTLD_LAZY); - if (h2 == NULL) - { - printf ("cannot open reldepmod4.so: %s\n", dlerror ()); - exit (1); - } - - /* Get the address of the variable in reldepmod1.so. */ - vp = dlsym (h1, "some_var"); - if (vp == NULL) - { - printf ("cannot get address of \"some_var\": %s\n", dlerror ()); - exit (1); - } - - *vp = 42; - - /* Get the function `call_me' in the second object. This has a - dependency which is resolved by a definition in reldepmod1.so. */ - fp = dlsym (h2, "call_me"); - if (fp == NULL) - { - printf ("cannot get address of \"call_me\": %s\n", dlerror ()); - exit (1); - } - - /* Call the function. */ - if (fp () != 0) - { - puts ("function \"call_me\" returned wrong result"); - exit (1); - } - - /* Now close the first object. If must still be around since we have - an implicit dependency. */ - if (dlclose (h1) != 0) - { - printf ("closing h1 failed: %s\n", dlerror ()); - exit (1); - } - - /* Open the first object again. */ - h1 = dlopen ("reldepmod1.so", RTLD_LAZY | RTLD_GLOBAL); - if (h1 == NULL) - { - printf ("cannot open reldepmod1.so the second time: %s\n", dlerror ()); - exit (1); - } - - /* Get the variable address again. */ - vp = dlsym (h1, "some_var"); - if (vp == NULL) - { - printf ("cannot get address of \"some_var\" the second time: %s\n", - dlerror ()); - exit (1); - } - - /* The variable now must have its originial value. */ - if (*vp != 0) - { - puts ("variable \"some_var\" not reset"); - exit (1); - } - - /* Close the first object again, we are done. */ - if (dlclose (h1) != 0) - { - printf ("closing h1 failed: %s\n", dlerror ()); - exit (1); - } - if (dlclose (h2) != 0) - { - printf ("closing h2 failed: %s\n", dlerror ()); - exit (1); - } - - return 0; -} diff --git a/elf/reldep4.c b/elf/reldep4.c deleted file mode 100644 index ba12e7d9c4..0000000000 --- a/elf/reldep4.c +++ /dev/null @@ -1,40 +0,0 @@ -#include <dlfcn.h> -#include <mcheck.h> -#include <stdio.h> -#include <stdlib.h> - -int -main (void) -{ - int i; - void *h1, *h2; - - mtrace (); - - for (i = 0; i < 3; i++) - { - h1 = dlopen ("reldep4mod1.so", RTLD_NOW | RTLD_GLOBAL); - if (h1 == NULL) - { - printf ("cannot open reldep4mod1.so: %s\n", dlerror ()); - exit (1); - } - h2 = dlopen ("reldep4mod2.so", RTLD_NOW | RTLD_GLOBAL); - if (h2 == NULL) - { - printf ("cannot open reldep4mod2.so: %s\n", dlerror ()); - exit (1); - } - if (dlclose (h1) != 0) - { - printf ("closing h1 failed: %s\n", dlerror ()); - exit (1); - } - if (dlclose (h2) != 0) - { - printf ("closing h2 failed: %s\n", dlerror ()); - exit (1); - } - } - return 0; -} diff --git a/elf/reldep4mod1.c b/elf/reldep4mod1.c deleted file mode 100644 index 934a68096e..0000000000 --- a/elf/reldep4mod1.c +++ /dev/null @@ -1,7 +0,0 @@ -int foo (void); - -int foo (void) -{ - return 0; -} - diff --git a/elf/reldep4mod2.c b/elf/reldep4mod2.c deleted file mode 100644 index 26ce6bf13a..0000000000 --- a/elf/reldep4mod2.c +++ /dev/null @@ -1,8 +0,0 @@ -extern int foo (void); -extern int bar (void); - -int -bar (void) -{ - return foo (); -} diff --git a/elf/reldep4mod3.c b/elf/reldep4mod3.c deleted file mode 100644 index 934a68096e..0000000000 --- a/elf/reldep4mod3.c +++ /dev/null @@ -1,7 +0,0 @@ -int foo (void); - -int foo (void) -{ - return 0; -} - diff --git a/elf/reldep4mod4.c b/elf/reldep4mod4.c deleted file mode 100644 index 26ce6bf13a..0000000000 --- a/elf/reldep4mod4.c +++ /dev/null @@ -1,8 +0,0 @@ -extern int foo (void); -extern int bar (void); - -int -bar (void) -{ - return foo (); -} diff --git a/elf/reldep5.c b/elf/reldep5.c deleted file mode 100644 index 881d519ff6..0000000000 --- a/elf/reldep5.c +++ /dev/null @@ -1,70 +0,0 @@ -#include <dlfcn.h> -#include <mcheck.h> -#include <stdio.h> -#include <stdlib.h> - -int -main (void) -{ - void *h1; - void *h2; - int (*fp) (void); - - mtrace (); - - /* Open the two objects. */ - h1 = dlopen ("reldepmod5.so", RTLD_LAZY); - if (h1 == NULL) - { - printf ("cannot open reldepmod5.so: %s\n", dlerror ()); - exit (1); - } - h2 = dlopen ("reldepmod6.so", RTLD_LAZY); - if (h2 == NULL) - { - printf ("cannot open reldepmod6.so: %s\n", dlerror ()); - exit (1); - } - - /* Get the address of the variable in reldepmod1.so. */ - fp = dlsym (h2, "bar"); - if (fp == NULL) - { - printf ("cannot get address of \"bar\": %s\n", dlerror ()); - exit (1); - } - - /* Call the function. */ - puts ("calling fp for the first time"); - if (fp () != 0) - { - puts ("function \"call_me\" returned wrong result"); - exit (1); - } - - /* Now close the first object. It must still be around since we have - an implicit dependency. */ - if (dlclose (h1) != 0) - { - printf ("closing h1 failed: %s\n", dlerror ()); - exit (1); - } - - /* Calling the function must still work. */ - puts ("calling fp for the second time"); - if (fp () != 0) - { - puts ("function \"call_me\" the second time returned wrong result"); - exit (1); - } - puts ("second call suceeded as well"); - - /* Close the second object, we are done. */ - if (dlclose (h2) != 0) - { - printf ("closing h2 failed: %s\n", dlerror ()); - exit (1); - } - - return 0; -} diff --git a/elf/reldep6.c b/elf/reldep6.c deleted file mode 100644 index 1eeec6c862..0000000000 --- a/elf/reldep6.c +++ /dev/null @@ -1,109 +0,0 @@ -#include <dlfcn.h> -#include <mcheck.h> -#include <stdio.h> -#include <stdlib.h> - -typedef int (*fn)(void); -#define CHUNKS 1024 -#define REPEAT 64 - -int -main (void) -{ - void *h1; - void *h2; - fn **foopp; - fn bar, baz; - int i, j; - int n; - void *allocs[REPEAT][CHUNKS]; - - mtrace (); - - /* Open the two objects. */ - h1 = dlopen ("reldep6mod3.so", RTLD_LAZY); - if (h1 == NULL) - { - printf ("cannot open reldep6mod3.so: %s\n", dlerror ()); - exit (1); - } - - foopp = dlsym (h1, "foopp"); - if (foopp == NULL) - { - printf ("cannot get address of \"foopp\": %s\n", dlerror ()); - exit (1); - } - n = (**foopp) (); - if (n != 20) - { - printf ("(**foopp)() return %d, not return 20\n", n); - exit (1); - } - - h2 = dlopen ("reldep6mod4.so", RTLD_LAZY); - if (h2 == NULL) - { - printf ("cannot open reldep6mod4.so: %s\n", dlerror ()); - exit (1); - } - - baz = dlsym (h2, "baz"); - if (baz == NULL) - { - printf ("cannot get address of \"baz\": %s\n", dlerror ()); - exit (1); - } - if (baz () != 31) - { - printf ("baz() did not return 31\n"); - exit (1); - } - - if (dlclose (h1) != 0) - { - printf ("closing h1 failed: %s\n", dlerror ()); - exit (1); - } - - /* Clobber memory. */ - for (i = 0; i < REPEAT; ++i) - for (j = 0; j < CHUNKS; ++j) - allocs[i][j] = calloc (1, j + 1); - - bar = dlsym (h2, "bar"); - if (bar == NULL) - { - printf ("cannot get address of \"bar\": %s\n", dlerror ()); - exit (1); - } - if (bar () != 40) - { - printf ("bar() did not return 40\n"); - exit (1); - } - - baz = dlsym (h2, "baz"); - if (baz == NULL) - { - printf ("cannot get address of \"baz\": %s\n", dlerror ()); - exit (1); - } - if (baz () != 31) - { - printf ("baz() did not return 31\n"); - exit (1); - } - - for (i = 0; i < REPEAT; ++i) - for (j = 0; j < CHUNKS; ++j) - free (allocs[i][j]); - - if (dlclose (h2) != 0) - { - printf ("closing h2 failed: %s\n", dlerror ()); - exit (1); - } - - return 0; -} diff --git a/elf/reldep6mod0.c b/elf/reldep6mod0.c deleted file mode 100644 index 58f3745fb4..0000000000 --- a/elf/reldep6mod0.c +++ /dev/null @@ -1,8 +0,0 @@ -int bar (void); -extern void free (void *); - -int bar (void) -{ - free (0); - return 40; -} diff --git a/elf/reldep6mod1.c b/elf/reldep6mod1.c deleted file mode 100644 index 037a73a198..0000000000 --- a/elf/reldep6mod1.c +++ /dev/null @@ -1,14 +0,0 @@ -int foo (void); -int baz (void); -extern int weak (void); -asm (".weak weak"); - -int foo (void) -{ - return 20; -} - -int baz (void) -{ - return weak () + 1; -} diff --git a/elf/reldep6mod2.c b/elf/reldep6mod2.c deleted file mode 100644 index c2ef3f9bc0..0000000000 --- a/elf/reldep6mod2.c +++ /dev/null @@ -1,3 +0,0 @@ -extern int foo (void); - -void *foop = (void *) foo; diff --git a/elf/reldep6mod3.c b/elf/reldep6mod3.c deleted file mode 100644 index 881828ef6e..0000000000 --- a/elf/reldep6mod3.c +++ /dev/null @@ -1,3 +0,0 @@ -extern void *foop; - -void **foopp = &foop; diff --git a/elf/reldep6mod4.c b/elf/reldep6mod4.c deleted file mode 100644 index 8fa89de64b..0000000000 --- a/elf/reldep6mod4.c +++ /dev/null @@ -1,12 +0,0 @@ -int foo (void); -int weak (void); - -int foo (void) -{ - return 10; -} - -int weak (void) -{ - return 30; -} diff --git a/elf/reldep7.c b/elf/reldep7.c deleted file mode 100644 index 5275a0e8f1..0000000000 --- a/elf/reldep7.c +++ /dev/null @@ -1,58 +0,0 @@ -#include <dlfcn.h> -#include <stdio.h> -#include <stdlib.h> - -int -main (void) -{ - void *h1; - void *h2; - void *mod1_bar, *mod2_bar; - - h1 = dlopen ("reldep7mod1.so", RTLD_GLOBAL | RTLD_LAZY); - if (h1 == NULL) - { - printf ("cannot open reldep7mod1.so: %s\n", dlerror ()); - exit (1); - } - - h2 = dlopen ("reldep7mod2.so", RTLD_GLOBAL | RTLD_LAZY); - if (h2 == NULL) - { - printf ("cannot open reldep7mod1.so: %s\n", dlerror ()); - exit (1); - } - - mod1_bar = dlsym (h1, "mod1_bar"); - if (mod1_bar == NULL) - { - printf ("cannot get address of \"mod1_bar\": %s\n", dlerror ()); - exit (1); - } - - mod2_bar = dlsym (h2, "mod2_bar"); - if (mod2_bar == NULL) - { - printf ("cannot get address of \"mod2_bar\": %s\n", dlerror ()); - exit (1); - } - - printf ("%d\n", ((int (*) (void)) mod1_bar) ()); - printf ("%d\n", ((int (*) (void)) mod2_bar) ()); - - if (dlclose (h1) != 0) - { - printf ("closing h1 failed: %s\n", dlerror ()); - exit (1); - } - - printf ("%d\n", ((int (*) (void)) mod2_bar) ()); - - if (dlclose (h2) != 0) - { - printf ("closing h2 failed: %s\n", dlerror ()); - exit (1); - } - - return 0; -} diff --git a/elf/reldep7mod1.c b/elf/reldep7mod1.c deleted file mode 100644 index de1bb3a6cd..0000000000 --- a/elf/reldep7mod1.c +++ /dev/null @@ -1,12 +0,0 @@ -int foo (void) __attribute__ ((weak)); -int -foo (void) -{ - return 1; -} - -int -mod1_bar (void) -{ - return foo (); -} diff --git a/elf/reldep7mod2.c b/elf/reldep7mod2.c deleted file mode 100644 index 3fa3368792..0000000000 --- a/elf/reldep7mod2.c +++ /dev/null @@ -1,12 +0,0 @@ -int foo (void) __attribute__ ((weak)); -int -foo (void) -{ - return 2; -} - -int -mod2_bar (void) -{ - return foo (); -} diff --git a/elf/reldep8.c b/elf/reldep8.c deleted file mode 100644 index 90009a5609..0000000000 --- a/elf/reldep8.c +++ /dev/null @@ -1,16 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> -#include <dlfcn.h> - -int -main (void) -{ - void *handle = dlopen ("reldep8mod3.so", RTLD_LAZY); - if (handle == NULL) - { - printf ("%s\n", dlerror ()); - exit (1); - } - dlclose (handle); - abort (); -} diff --git a/elf/reldep8mod1.c b/elf/reldep8mod1.c deleted file mode 100644 index acddc4cf8b..0000000000 --- a/elf/reldep8mod1.c +++ /dev/null @@ -1,19 +0,0 @@ -#include <stdlib.h> -void -foo (void) -{ - exit (0); -} - -void -__attribute__((destructor)) -bar (void) -{ - static int i; - foo (); - ++i; -} -void -baz (void) -{ -} diff --git a/elf/reldep8mod2.c b/elf/reldep8mod2.c deleted file mode 100644 index d0020240a8..0000000000 --- a/elf/reldep8mod2.c +++ /dev/null @@ -1,7 +0,0 @@ -void -__attribute__((constructor)) -xxx (void) -{ - extern void baz (void); - baz (); -} diff --git a/elf/reldep8mod3.c b/elf/reldep8mod3.c deleted file mode 100644 index 6d1a0d47b7..0000000000 --- a/elf/reldep8mod3.c +++ /dev/null @@ -1 +0,0 @@ -int x; diff --git a/elf/reldep9.c b/elf/reldep9.c deleted file mode 100644 index 51c7a8bb9e..0000000000 --- a/elf/reldep9.c +++ /dev/null @@ -1,16 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> -#include <dlfcn.h> - -int -main (void) -{ - void *handle = dlopen ("reldep9mod3.so", RTLD_LAZY); - if (handle == NULL) - { - printf ("%s\n", dlerror ()); - exit (1); - } - dlclose (handle); - abort (); -} diff --git a/elf/reldep9mod1.c b/elf/reldep9mod1.c deleted file mode 100644 index 249a2bae1c..0000000000 --- a/elf/reldep9mod1.c +++ /dev/null @@ -1,23 +0,0 @@ -#include <stdlib.h> -void -foo (void) -{ - exit (0); -} - -void -__attribute__((destructor)) -bar (void) -{ - static int i; - foo (); - ++i; -} - -void -__attribute__((constructor)) -destr (void) -{ - extern void baz (void); - baz (); -} diff --git a/elf/reldep9mod2.c b/elf/reldep9mod2.c deleted file mode 100644 index 090966e3e3..0000000000 --- a/elf/reldep9mod2.c +++ /dev/null @@ -1,3 +0,0 @@ -void baz (void) -{ -} diff --git a/elf/reldep9mod3.c b/elf/reldep9mod3.c deleted file mode 100644 index 6d1a0d47b7..0000000000 --- a/elf/reldep9mod3.c +++ /dev/null @@ -1 +0,0 @@ -int x; diff --git a/elf/reldepmod1.c b/elf/reldepmod1.c deleted file mode 100644 index b8ef6401e1..0000000000 --- a/elf/reldepmod1.c +++ /dev/null @@ -1,10 +0,0 @@ -extern int foo (void); - -int some_var; - - -int -foo (void) -{ - return some_var; -} diff --git a/elf/reldepmod2.c b/elf/reldepmod2.c deleted file mode 100644 index b7edebae80..0000000000 --- a/elf/reldepmod2.c +++ /dev/null @@ -1,8 +0,0 @@ -extern int foo (void); -extern int call_me (void); - -int -call_me (void) -{ - return foo () - 42; -} diff --git a/elf/reldepmod3.c b/elf/reldepmod3.c deleted file mode 100644 index 66a996cd90..0000000000 --- a/elf/reldepmod3.c +++ /dev/null @@ -1,20 +0,0 @@ -#include <dlfcn.h> -#include <stdio.h> -#include <stdlib.h> - -extern int call_me (void); - -int -call_me (void) -{ - int (*fp) (void); - - fp = dlsym (RTLD_DEFAULT, "foo"); - if (fp == NULL) - { - printf ("cannot get address of foo in global scope: %s\n", dlerror ()); - exit (1); - } - - return fp () - 42; -} diff --git a/elf/reldepmod4.c b/elf/reldepmod4.c deleted file mode 100644 index dcb503bba7..0000000000 --- a/elf/reldepmod4.c +++ /dev/null @@ -1,37 +0,0 @@ -#include <dlfcn.h> -#include <stdio.h> -#include <stdlib.h> - -extern int call_me (void); - -int -call_me (void) -{ - void *h; - int (*fp) (void); - int res; - - h = dlopen ("reldepmod1.so", RTLD_LAZY); - if (h == NULL) - { - printf ("cannot open reldepmod1.so in %s: %s\n", __FILE__, dlerror ()); - exit (1); - } - - fp = dlsym (h, "foo"); - if (fp == NULL) - { - printf ("cannot get address of foo in global scope: %s\n", dlerror ()); - exit (1); - } - - res = fp () - 42; - - if (dlclose (h) != 0) - { - printf ("failure when closing h in %s: %s\n", __FILE__, dlerror ()); - exit (1); - } - - return res; -} diff --git a/elf/reldepmod5.c b/elf/reldepmod5.c deleted file mode 100644 index 62df697162..0000000000 --- a/elf/reldepmod5.c +++ /dev/null @@ -1,7 +0,0 @@ -extern int foo (void); - -int -foo (void) -{ - return 42; -} diff --git a/elf/reldepmod6.c b/elf/reldepmod6.c deleted file mode 100644 index cd2aeb400d..0000000000 --- a/elf/reldepmod6.c +++ /dev/null @@ -1,8 +0,0 @@ -extern int call_me (void); -extern int bar (void); - -int -bar (void) -{ - return call_me (); -} diff --git a/elf/resolvfail.c b/elf/resolvfail.c deleted file mode 100644 index ebd635d153..0000000000 --- a/elf/resolvfail.c +++ /dev/null @@ -1,31 +0,0 @@ -#include <dlfcn.h> -#include <stdio.h> - -static const char obj[] = "testobj1.so"; - -int -main (void) -{ - void *d = dlopen (obj, RTLD_LAZY); - int n; - - if (d == NULL) - { - printf ("cannot load %s: %s\n", obj, dlerror ()); - return 1; - } - - for (n = 0; n < 10000; ++n) - if (dlsym (d, "does not exist") != NULL) - { - puts ("dlsym() did not fail"); - return 1; - } - else if (dlerror () == NULL) - { - puts ("dlerror() didn't return a string"); - return 1; - } - - return 0; -} diff --git a/elf/restest1.c b/elf/restest1.c deleted file mode 100644 index eb5aeca59e..0000000000 --- a/elf/restest1.c +++ /dev/null @@ -1,57 +0,0 @@ -#include <dlfcn.h> -#include <error.h> -#include <mcheck.h> -#include <stdio.h> -#include <stdlib.h> - -int -main (void) -{ - void *h1; - int (*fp1) (int); - void *h2; - int (*fp2) (int); - int res1; - int res2; - - mtrace (); - - h1 = dlopen ("testobj1.so", RTLD_LAZY); - if (h1 == NULL) - error (EXIT_FAILURE, 0, "while loading `%s': %s", "testobj1.so", - dlerror ()); - - h2 = dlopen ("testobj1_1.so", RTLD_LAZY); - if (h1 == NULL) - error (EXIT_FAILURE, 0, "while loading `%s': %s", "testobj1_1.so", - dlerror ()); - - fp1 = dlsym (h1, "obj1func1"); - if (fp1 == NULL) - error (EXIT_FAILURE, 0, "getting `obj1func1' in `%s': %s", - "testobj1.so", dlerror ()); - - fp2 = dlsym (h2, "obj1func1"); - if (fp2 == NULL) - error (EXIT_FAILURE, 0, "getting `obj1func1' in `%s': %s", - "testobj1_1.so", dlerror ()); - - res1 = fp1 (10); - res2 = fp2 (10); - printf ("fp1(10) = %d\nfp2(10) = %d\n", res1, res2); - - if (dlclose (h1) != 0) - error (EXIT_FAILURE, 0, "cannot close testobj1.so: %s\n", dlerror ()); - if (dlclose (h2) != 0) - error (EXIT_FAILURE, 0, "cannot close testobj1_1.so: %s\n", dlerror ()); - - return res1 != 42 || res2 != 72; -} - - -extern int foo (int a); -int -foo (int a) -{ - return a + 10; -} diff --git a/elf/restest2.c b/elf/restest2.c deleted file mode 100644 index f959f030a0..0000000000 --- a/elf/restest2.c +++ /dev/null @@ -1,33 +0,0 @@ -#include <sys/types.h> -#include <dlfcn.h> -#include <error.h> -#include <mcheck.h> -#include <stdlib.h> -#include <unistd.h> - -pid_t pid, pid2; - -pid_t getpid(void) -{ - pid_t (*f)(void); - f = (pid_t (*)(void)) dlsym (RTLD_NEXT, "getpid"); - if (f == NULL) - error (EXIT_FAILURE, 0, "dlsym (RTLD_NEXT, \"getpid\"): %s", dlerror ()); - return (pid2 = f()) + 26; -} - -int -main (void) -{ - pid_t (*f)(void); - - mtrace (); - - f = (pid_t (*)(void)) dlsym (RTLD_DEFAULT, "getpid"); - if (f == NULL) - error (EXIT_FAILURE, 0, "dlsym (RTLD_DEFAULT, \"getpid\"): %s", dlerror ()); - pid = f(); - if (pid != pid2 + 26) - error (EXIT_FAILURE, 0, "main getpid() not called"); - return 0; -} diff --git a/elf/rtld-Rules b/elf/rtld-Rules deleted file mode 100644 index 2c7b99828c..0000000000 --- a/elf/rtld-Rules +++ /dev/null @@ -1,149 +0,0 @@ -# Subroutine makefile for compiling libc modules linked into dynamic linker. - -# Copyright (C) 2002-2017 Free Software Foundation, Inc. -# This file is part of the GNU C Library. - -# The GNU C Library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. - -# The GNU C Library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. - -# You should have received a copy of the GNU Lesser General Public -# License along with the GNU C Library; if not, see -# <http://www.gnu.org/licenses/>. - -# This makefile is never used by itself, but only from the rtld-libc.a -# rule in Makefile, which does make -f librtld.mk -f rtld-Rules. -# librtld.mk is the generated file containing variable definitions for -# `rtld-subdirs', a subset of the top-level $(subdirs) list; and for each -# SUBDIR in $(rtld-subdirs), `rtld-SUBDIR' listing `module.os' file names. - -.PHONY: rtld-all -rtld-all: - -# When run from the elf/Makefile to build rtld-libc.a, $(subdir) is elf. -ifneq ($(subdir),elf) -ifndef rtld-modules -error rtld-modules not set -endif -endif - -ifndef rtld-modules -# Running to build rtld-libc.a, driving runs of $(rtld-subdir-make), below. - -ifndef rtld-subdirs -error This makefile is a subroutine of elf/Makefile not to be used directly -endif - -include ../Makeconfig - -rtld-all: $(objpfx)rtld-libc.a - -$(objpfx)rtld-libc.a: $(foreach dir,$(rtld-subdirs),\ - $(addprefix $(common-objpfx)$(dir)/rtld-,\ - $(rtld-$(dir)))) - @-rm -f $@T - $(AR) cq$(verbose) $@T $^ - mv -f $@T $@ - -# Use the verbose option of ar and tar when not running silently. -ifeq "$(findstring s,$(MAKEFLAGS))" "" # if not -s -verbose := v -else # -s -verbose := -endif # not -s - - -# For each subdirectory, define a pattern rule that makes all of that -# subdirectory's modules at once with one recursive make command. -object-suffixes-left := $(rtld-subdirs) -define o-iterator-doit -$(foreach obj,$(rtld-$o),$(common-objpfx)%/rtld-$(obj)): FORCE ; \ - +$$(rtld-subdir-make) -endef -include $(patsubst %,../o-iterator.mk,$(object-suffixes-left)) - -# This is how we descend into each subdirectory. See below. -define rtld-subdir-make -$(MAKE) $(subdir-args) objdir=$(objdir) \ - -f Makefile -f ../elf/rtld-Rules rtld-all \ - rtld-modules='$(addprefix rtld-,$(rtld-$*))' -endef - -# See subdir-target-args in ../Makefile for the model. -subdir-args = subdir=$*$(if $($*-srcdir),\ - -C $($*-srcdir) ..=`pwd`/,\ - -C $(..)$* ..=../) - -FORCE: - -else - -# In this case we are being run by $(rtld-subdir-make), above. -# Some other subdir's Makefile has provided all its normal rules, -# and we just provide some additional definitions. - -rtld-compile-command.S = $(compile-command.S) $(rtld-CPPFLAGS) -rtld-compile-command.s = $(compile-command.s) $(rtld-CPPFLAGS) -rtld-compile-command.c = $(compile-command.c) $(rtld-CPPFLAGS) $(rtld-CFLAGS) - -# These are the basic compilation rules corresponding to the Makerules ones. -# The sysd-rules generated makefile already defines pattern rules for rtld-% -# targets built from sysdeps source files. -$(objpfx)rtld-%.os: rtld-%.S $(before-compile) - $(rtld-compile-command.S) -$(objpfx)rtld-%.os: rtld-%.s $(before-compile) - $(rtld-compile-command.s) -$(objpfx)rtld-%.os: rtld-%.c $(before-compile) - $(rtld-compile-command.c) -$(objpfx)rtld-%.os: %.S $(before-compile) - $(rtld-compile-command.S) -$(objpfx)rtld-%.os: %.s $(before-compile) - $(rtld-compile-command.s) -$(objpfx)rtld-%.os: %.c $(before-compile) - $(rtld-compile-command.c) - -# The rules for generated source files. -$(objpfx)rtld-%.os: $(objpfx)rtld-%.S $(before-compile) - $(rtld-compile-command.S) -$(objpfx)rtld-%.os: $(objpfx)rtld-%.s $(before-compile) - $(rtld-compile-command.s) -$(objpfx)rtld-%.os: $(objpfx)rtld-%.c $(before-compile) - $(rtld-compile-command.c) -$(objpfx)rtld-%.os: $(objpfx)%.S $(before-compile) - $(rtld-compile-command.S) -$(objpfx)rtld-%.os: $(objpfx)%.s $(before-compile) - $(rtld-compile-command.s) -$(objpfx)rtld-%.os: $(objpfx)%.c $(before-compile) - $(rtld-compile-command.c) - -# The command line setting of rtld-modules (see above) tells us -# what we need to build, and that tells us what dependency files we need. -rtld-all: $(addprefix $(objpfx),$(rtld-modules)) - -# Figure out the dependency files we need. After respecting the $(omit-deps) -# list as applied to the names without the `rtld-', there may be none left. -rtld-depfiles := $(patsubst %,$(objpfx)rtld-%.os.d,\ - $(filter-out $(omit-deps),\ - $(rtld-modules:rtld-%.os=%))) -rtld-depfiles := $(strip $(wildcard $(rtld-depfiles)) \ - $(patsubst %.dt,%.d,\ - $(wildcard $(rtld-depfiles:.d=.dt)))) -ifdef rtld-depfiles --include $(rtld-depfiles) -endif - -# This here is the whole point of all the shenanigans. -# Set libof-* for each routine. -cpp-srcs-left := $(rtld-modules:%.os=%) -lib := rtld -include $(patsubst %,$(..)libof-iterator.mk,$(cpp-srcs-left)) - -rtld-CFLAGS += $(no-stack-protector) - -endif diff --git a/elf/rtld-debugger-interface.txt b/elf/rtld-debugger-interface.txt deleted file mode 100644 index 61bc99e4b0..0000000000 --- a/elf/rtld-debugger-interface.txt +++ /dev/null @@ -1,122 +0,0 @@ -Standard debugger interface -=========================== - -The run-time linker exposes a rendezvous structure to allow debuggers -to interface with it. This structure, r_debug, is defined in link.h. -If the executable's dynamic section has a DT_DEBUG element, the -run-time linker sets that element's value to the address where this -structure can be found. - -The r_debug structure contains (amongst others) the following fields: - - struct link_map *r_map: - A linked list of loaded objects. - - enum { RT_CONSISTENT, RT_ADD, RT_DELETE } r_state: - The current state of the r_map list. RT_CONSISTENT means that r_map - is not currently being modified and may safely be inspected. RT_ADD - means that an object is being added to r_map, and that the list is - not guaranteed to be consistent. Likewise RT_DELETE means that an - object is being removed from the list. - - ElfW(Addr) r_brk: - The address of a function internal to the run-time linker which is - called whenever r_state is changed. The debugger should set a - breakpoint at this address if it wants to notice mapping changes. - -This protocol is widely supported, but somewhat limited in that it -has no provision to provide access to multiple namespaces, and that -the notifications (via r_brk) only refer to changes to r_map--the -debugger is notified that a new object has been added, for instance, -but there is no way for the debugger to discover whether any of the -objects in the link-map have been relocated or not. - - -Probe-based debugger interface -============================== - -Systemtap is a dynamic tracing/instrumenting tool available on Linux. -Probes that are not fired at run time have close to zero overhead. -glibc contains a number of probes that debuggers can set breakpoints -on in order to notice certain events. - -All rtld probes have the following arguments: - - arg1: Lmid_t lmid: - The link-map ID of the link-map list that the object was loaded - into. This will be LM_ID_BASE for the application's main link-map - list, or some other value for different namespaces. - - arg2: struct r_debug *r_debug: - A pointer to the r_debug structure containing the link-map list - that the object was loaded into. This will be the value stored in - DT_DEBUG for the application's main link-map list, or some other - value for different namespaces. - -map_complete and reloc_complete may have the following additional -argument: - - arg3: struct link_map *new: - A pointer which, if not NULL, points to the entry in the specified - r_debug structure's link-map list corresponding to the first new - object to have been mapped or relocated, with new->l_next pointing - to the link-map of the next new object to have been mapped or - relocated, and so on. Note that because `new' is an entry in a - larger list, new->l_prev (if not NULL) will point to what was the - last link-map in the link-map list prior to the new objects being - mapped or relocated. - -The following probes are available: - - init_start: - This is called once, when the linker is about to fill in the main - r_debug structure at application startup. init_start always has - lmid set to LM_ID_BASE and r_debug set to the value stored in - DT_DEBUG. r_debug is not guaranteed to be consistent until - init_complete is fired. - - init_complete: - This is called once, when the linker has filled in the main - r_debug structure at application startup. init_complete always - has lmid set to LM_ID_BASE and r_debug set to the value stored - in DT_DEBUG. The r_debug structure is consistent and may be - inspected, and all objects in the link-map are guaranteed to - have been relocated. - - map_start: - The linker is about to map new objects into the specified - namespace. The namespace's r_debug structure is not guaranteed - to be consistent until a corresponding map_complete is fired. - - map_complete: - The linker has finished mapping new objects into the specified - namespace. The namespace's r_debug structure is consistent and - may be inspected, although objects in the namespace's link-map - are not guaranteed to have been relocated. - - map_failed: - The linker failed while attempting to map new objects into - the specified namespace. The namespace's r_debug structure - is consistent and may be inspected. - - reloc_start: - The linker is about to relocate all unrelocated objects in the - specified namespace. The namespace's r_debug structure is not - guaranteed to be consistent until a corresponding reloc_complete - is fired. - - reloc_complete: - The linker has relocated all objects in the specified namespace. - The namespace's r_debug structure is consistent and may be - inspected, and all objects in the namespace's link-map are - guaranteed to have been relocated. - - unmap_start: - The linker is about to remove objects from the specified - namespace. The namespace's r_debug structure is not guaranteed to - be consistent until a corresponding unmap_complete is fired. - - unmap_complete: - The linker has finished removing objects into the specified - namespace. The namespace's r_debug structure is consistent and - may be inspected. diff --git a/elf/rtld.c b/elf/rtld.c deleted file mode 100644 index 3746653afb..0000000000 --- a/elf/rtld.c +++ /dev/null @@ -1,2652 +0,0 @@ -/* Run time dynamic linker. - Copyright (C) 1995-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -#include <errno.h> -#include <dlfcn.h> -#include <fcntl.h> -#include <stdbool.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <sys/mman.h> -#include <sys/param.h> -#include <sys/stat.h> -#include <ldsodefs.h> -#include <_itoa.h> -#include <entry.h> -#include <fpu_control.h> -#include <hp-timing.h> -#include <libc-lock.h> -#include "dynamic-link.h" -#include <dl-librecon.h> -#include <unsecvars.h> -#include <dl-cache.h> -#include <dl-osinfo.h> -#include <dl-procinfo.h> -#include <tls.h> -#include <stap-probe.h> -#include <stackinfo.h> - -#include <assert.h> - -/* Avoid PLT use for our local calls at startup. */ -extern __typeof (__mempcpy) __mempcpy attribute_hidden; - -/* GCC has mental blocks about _exit. */ -extern __typeof (_exit) exit_internal asm ("_exit") attribute_hidden; -#define _exit exit_internal - -/* Helper function to handle errors while resolving symbols. */ -static void print_unresolved (int errcode, const char *objname, - const char *errsting); - -/* Helper function to handle errors when a version is missing. */ -static void print_missing_version (int errcode, const char *objname, - const char *errsting); - -/* Print the various times we collected. */ -static void print_statistics (hp_timing_t *total_timep); - -/* Add audit objects. */ -static void process_dl_audit (char *str); - -/* This is a list of all the modes the dynamic loader can be in. */ -enum mode { normal, list, verify, trace }; - -/* Process all environments variables the dynamic linker must recognize. - Since all of them start with `LD_' we are a bit smarter while finding - all the entries. */ -static void process_envvars (enum mode *modep); - -#ifdef DL_ARGV_NOT_RELRO -int _dl_argc attribute_hidden; -char **_dl_argv = NULL; -/* Nonzero if we were run directly. */ -unsigned int _dl_skip_args attribute_hidden; -#else -int _dl_argc attribute_relro attribute_hidden; -char **_dl_argv attribute_relro = NULL; -unsigned int _dl_skip_args attribute_relro attribute_hidden; -#endif -rtld_hidden_data_def (_dl_argv) - -#ifndef THREAD_SET_STACK_GUARD -/* Only exported for architectures that don't store the stack guard canary - in thread local area. */ -uintptr_t __stack_chk_guard attribute_relro; -#endif - -/* Only exported for architectures that don't store the pointer guard - value in thread local area. */ -uintptr_t __pointer_chk_guard_local - attribute_relro attribute_hidden __attribute__ ((nocommon)); -#ifndef THREAD_SET_POINTER_GUARD -strong_alias (__pointer_chk_guard_local, __pointer_chk_guard) -#endif - - -/* List of auditing DSOs. */ -static struct audit_list -{ - const char *name; - struct audit_list *next; -} *audit_list; - -#ifndef HAVE_INLINED_SYSCALLS -/* Set nonzero during loading and initialization of executable and - libraries, cleared before the executable's entry point runs. This - must not be initialized to nonzero, because the unused dynamic - linker loaded in for libc.so's "ld.so.1" dep will provide the - definition seen by libc.so's initializer; that value must be zero, - and will be since that dynamic linker's _dl_start and dl_main will - never be called. */ -int _dl_starting_up = 0; -rtld_hidden_def (_dl_starting_up) -#endif - -/* This is the structure which defines all variables global to ld.so - (except those which cannot be added for some reason). */ -struct rtld_global _rtld_global = - { - /* Generally the default presumption without further information is an - * executable stack but this is not true for all platforms. */ - ._dl_stack_flags = DEFAULT_STACK_PERMS, -#ifdef _LIBC_REENTRANT - ._dl_load_lock = _RTLD_LOCK_RECURSIVE_INITIALIZER, - ._dl_load_write_lock = _RTLD_LOCK_RECURSIVE_INITIALIZER, -#endif - ._dl_nns = 1, - ._dl_ns = - { -#ifdef _LIBC_REENTRANT - [LM_ID_BASE] = { ._ns_unique_sym_table - = { .lock = _RTLD_LOCK_RECURSIVE_INITIALIZER } } -#endif - } - }; -/* If we would use strong_alias here the compiler would see a - non-hidden definition. This would undo the effect of the previous - declaration. So spell out was strong_alias does plus add the - visibility attribute. */ -extern struct rtld_global _rtld_local - __attribute__ ((alias ("_rtld_global"), visibility ("hidden"))); - - -/* This variable is similar to _rtld_local, but all values are - read-only after relocation. */ -struct rtld_global_ro _rtld_global_ro attribute_relro = - { - /* Get architecture specific initializer. */ -#include <dl-procinfo.c> -#ifdef NEED_DL_SYSINFO - ._dl_sysinfo = DL_SYSINFO_DEFAULT, -#endif - ._dl_debug_fd = STDERR_FILENO, - ._dl_use_load_bias = -2, - ._dl_correct_cache_id = _DL_CACHE_DEFAULT_ID, -#if !HAVE_TUNABLES - ._dl_hwcap_mask = HWCAP_IMPORTANT, -#endif - ._dl_lazy = 1, - ._dl_fpu_control = _FPU_DEFAULT, - ._dl_pagesize = EXEC_PAGESIZE, - ._dl_inhibit_cache = 0, - - /* Function pointers. */ - ._dl_debug_printf = _dl_debug_printf, - ._dl_mcount = _dl_mcount, - ._dl_lookup_symbol_x = _dl_lookup_symbol_x, - ._dl_check_caller = _dl_check_caller, - ._dl_open = _dl_open, - ._dl_close = _dl_close, - ._dl_tls_get_addr_soft = _dl_tls_get_addr_soft, -#ifdef HAVE_DL_DISCOVER_OSVERSION - ._dl_discover_osversion = _dl_discover_osversion -#endif - }; -/* If we would use strong_alias here the compiler would see a - non-hidden definition. This would undo the effect of the previous - declaration. So spell out was strong_alias does plus add the - visibility attribute. */ -extern struct rtld_global_ro _rtld_local_ro - __attribute__ ((alias ("_rtld_global_ro"), visibility ("hidden"))); - - -static void dl_main (const ElfW(Phdr) *phdr, ElfW(Word) phnum, - ElfW(Addr) *user_entry, ElfW(auxv_t) *auxv); - -/* These two variables cannot be moved into .data.rel.ro. */ -static struct libname_list _dl_rtld_libname; -static struct libname_list _dl_rtld_libname2; - -/* Variable for statistics. */ -#ifndef HP_TIMING_NONAVAIL -static hp_timing_t relocate_time; -static hp_timing_t load_time attribute_relro; -static hp_timing_t start_time attribute_relro; -#endif - -/* Additional definitions needed by TLS initialization. */ -#ifdef TLS_INIT_HELPER -TLS_INIT_HELPER -#endif - -/* Helper function for syscall implementation. */ -#ifdef DL_SYSINFO_IMPLEMENTATION -DL_SYSINFO_IMPLEMENTATION -#endif - -/* Before ld.so is relocated we must not access variables which need - relocations. This means variables which are exported. Variables - declared as static are fine. If we can mark a variable hidden this - is fine, too. The latter is important here. We can avoid setting - up a temporary link map for ld.so if we can mark _rtld_global as - hidden. */ -#ifdef PI_STATIC_AND_HIDDEN -# define DONT_USE_BOOTSTRAP_MAP 1 -#endif - -#ifdef DONT_USE_BOOTSTRAP_MAP -static ElfW(Addr) _dl_start_final (void *arg); -#else -struct dl_start_final_info -{ - struct link_map l; -#if !defined HP_TIMING_NONAVAIL && HP_TIMING_INLINE - hp_timing_t start_time; -#endif -}; -static ElfW(Addr) _dl_start_final (void *arg, - struct dl_start_final_info *info); -#endif - -/* These defined magically in the linker script. */ -extern char _begin[] attribute_hidden; -extern char _etext[] attribute_hidden; -extern char _end[] attribute_hidden; - - -#ifdef RTLD_START -RTLD_START -#else -# error "sysdeps/MACHINE/dl-machine.h fails to define RTLD_START" -#endif - -/* This is the second half of _dl_start (below). It can be inlined safely - under DONT_USE_BOOTSTRAP_MAP, where it is careful not to make any GOT - references. When the tools don't permit us to avoid using a GOT entry - for _dl_rtld_global (no attribute_hidden support), we must make sure - this function is not inlined (see below). */ - -#ifdef DONT_USE_BOOTSTRAP_MAP -static inline ElfW(Addr) __attribute__ ((always_inline)) -_dl_start_final (void *arg) -#else -static ElfW(Addr) __attribute__ ((noinline)) -_dl_start_final (void *arg, struct dl_start_final_info *info) -#endif -{ - ElfW(Addr) start_addr; - - if (HP_SMALL_TIMING_AVAIL) - { - /* If it hasn't happen yet record the startup time. */ - if (! HP_TIMING_INLINE) - HP_TIMING_NOW (start_time); -#if !defined DONT_USE_BOOTSTRAP_MAP && !defined HP_TIMING_NONAVAIL - else - start_time = info->start_time; -#endif - } - - /* Transfer data about ourselves to the permanent link_map structure. */ -#ifndef DONT_USE_BOOTSTRAP_MAP - GL(dl_rtld_map).l_addr = info->l.l_addr; - GL(dl_rtld_map).l_ld = info->l.l_ld; - memcpy (GL(dl_rtld_map).l_info, info->l.l_info, - sizeof GL(dl_rtld_map).l_info); - GL(dl_rtld_map).l_mach = info->l.l_mach; - GL(dl_rtld_map).l_relocated = 1; -#endif - _dl_setup_hash (&GL(dl_rtld_map)); - GL(dl_rtld_map).l_real = &GL(dl_rtld_map); - GL(dl_rtld_map).l_map_start = (ElfW(Addr)) _begin; - GL(dl_rtld_map).l_map_end = (ElfW(Addr)) _end; - GL(dl_rtld_map).l_text_end = (ElfW(Addr)) _etext; - /* Copy the TLS related data if necessary. */ -#ifndef DONT_USE_BOOTSTRAP_MAP -# if NO_TLS_OFFSET != 0 - GL(dl_rtld_map).l_tls_offset = NO_TLS_OFFSET; -# endif -#endif - - HP_TIMING_NOW (GL(dl_cpuclock_offset)); - - /* Initialize the stack end variable. */ - __libc_stack_end = __builtin_frame_address (0); - - /* Call the OS-dependent function to set up life so we can do things like - file access. It will call `dl_main' (below) to do all the real work - of the dynamic linker, and then unwind our frame and run the user - entry point on the same stack we entered on. */ - start_addr = _dl_sysdep_start (arg, &dl_main); - -#ifndef HP_TIMING_NONAVAIL - hp_timing_t rtld_total_time; - if (HP_SMALL_TIMING_AVAIL) - { - hp_timing_t end_time; - - /* Get the current time. */ - HP_TIMING_NOW (end_time); - - /* Compute the difference. */ - HP_TIMING_DIFF (rtld_total_time, start_time, end_time); - } -#endif - - if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_STATISTICS)) - { -#ifndef HP_TIMING_NONAVAIL - print_statistics (&rtld_total_time); -#else - print_statistics (NULL); -#endif - } - - return start_addr; -} - -static ElfW(Addr) __attribute_used__ internal_function -_dl_start (void *arg) -{ -#ifdef DONT_USE_BOOTSTRAP_MAP -# define bootstrap_map GL(dl_rtld_map) -#else - struct dl_start_final_info info; -# define bootstrap_map info.l -#endif - - /* This #define produces dynamic linking inline functions for - bootstrap relocation instead of general-purpose relocation. - Since ld.so must not have any undefined symbols the result - is trivial: always the map of ld.so itself. */ -#define RTLD_BOOTSTRAP -#define RESOLVE_MAP(sym, version, flags) (&bootstrap_map) -#include "dynamic-link.h" - - if (HP_TIMING_INLINE && HP_SMALL_TIMING_AVAIL) -#ifdef DONT_USE_BOOTSTRAP_MAP - HP_TIMING_NOW (start_time); -#else - HP_TIMING_NOW (info.start_time); -#endif - - /* Partly clean the `bootstrap_map' structure up. Don't use - `memset' since it might not be built in or inlined and we cannot - make function calls at this point. Use '__builtin_memset' if we - know it is available. We do not have to clear the memory if we - do not have to use the temporary bootstrap_map. Global variables - are initialized to zero by default. */ -#ifndef DONT_USE_BOOTSTRAP_MAP -# ifdef HAVE_BUILTIN_MEMSET - __builtin_memset (bootstrap_map.l_info, '\0', sizeof (bootstrap_map.l_info)); -# else - for (size_t cnt = 0; - cnt < sizeof (bootstrap_map.l_info) / sizeof (bootstrap_map.l_info[0]); - ++cnt) - bootstrap_map.l_info[cnt] = 0; -# endif -#endif - - /* Figure out the run-time load address of the dynamic linker itself. */ - bootstrap_map.l_addr = elf_machine_load_address (); - - /* Read our own dynamic section and fill in the info array. */ - bootstrap_map.l_ld = (void *) bootstrap_map.l_addr + elf_machine_dynamic (); - elf_get_dynamic_info (&bootstrap_map, NULL); - -#if NO_TLS_OFFSET != 0 - bootstrap_map.l_tls_offset = NO_TLS_OFFSET; -#endif - -#ifdef ELF_MACHINE_BEFORE_RTLD_RELOC - ELF_MACHINE_BEFORE_RTLD_RELOC (bootstrap_map.l_info); -#endif - - if (bootstrap_map.l_addr || ! bootstrap_map.l_info[VALIDX(DT_GNU_PRELINKED)]) - { - /* Relocate ourselves so we can do normal function calls and - data access using the global offset table. */ - - ELF_DYNAMIC_RELOCATE (&bootstrap_map, 0, 0, 0); - } - bootstrap_map.l_relocated = 1; - - /* Please note that we don't allow profiling of this object and - therefore need not test whether we have to allocate the array - for the relocation results (as done in dl-reloc.c). */ - - /* Now life is sane; we can call functions and access global data. - Set up to use the operating system facilities, and find out from - the operating system's program loader where to find the program - header table in core. Put the rest of _dl_start into a separate - function, that way the compiler cannot put accesses to the GOT - before ELF_DYNAMIC_RELOCATE. */ - { -#ifdef DONT_USE_BOOTSTRAP_MAP - ElfW(Addr) entry = _dl_start_final (arg); -#else - ElfW(Addr) entry = _dl_start_final (arg, &info); -#endif - -#ifndef ELF_MACHINE_START_ADDRESS -# define ELF_MACHINE_START_ADDRESS(map, start) (start) -#endif - - return ELF_MACHINE_START_ADDRESS (GL(dl_ns)[LM_ID_BASE]._ns_loaded, entry); - } -} - - - -/* Now life is peachy; we can do all normal operations. - On to the real work. */ - -/* Some helper functions. */ - -/* Arguments to relocate_doit. */ -struct relocate_args -{ - struct link_map *l; - int reloc_mode; -}; - -struct map_args -{ - /* Argument to map_doit. */ - const char *str; - struct link_map *loader; - int mode; - /* Return value of map_doit. */ - struct link_map *map; -}; - -struct dlmopen_args -{ - const char *fname; - struct link_map *map; -}; - -struct lookup_args -{ - const char *name; - struct link_map *map; - void *result; -}; - -/* Arguments to version_check_doit. */ -struct version_check_args -{ - int doexit; - int dotrace; -}; - -static void -relocate_doit (void *a) -{ - struct relocate_args *args = (struct relocate_args *) a; - - _dl_relocate_object (args->l, args->l->l_scope, args->reloc_mode, 0); -} - -static void -map_doit (void *a) -{ - struct map_args *args = (struct map_args *) a; - 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); -} - -static void -dlmopen_doit (void *a) -{ - struct dlmopen_args *args = (struct dlmopen_args *) a; - args->map = _dl_open (args->fname, - (RTLD_LAZY | __RTLD_DLOPEN | __RTLD_AUDIT - | __RTLD_SECURE), - dl_main, LM_ID_NEWLM, _dl_argc, _dl_argv, - __environ); -} - -static void -lookup_doit (void *a) -{ - struct lookup_args *args = (struct lookup_args *) a; - const ElfW(Sym) *ref = NULL; - args->result = NULL; - lookup_t l = _dl_lookup_symbol_x (args->name, args->map, &ref, - args->map->l_local_scope, NULL, 0, - DL_LOOKUP_RETURN_NEWEST, NULL); - if (ref != NULL) - args->result = DL_SYMBOL_ADDRESS (l, ref); -} - -static void -version_check_doit (void *a) -{ - struct version_check_args *args = (struct version_check_args *) a; - if (_dl_check_all_versions (GL(dl_ns)[LM_ID_BASE]._ns_loaded, 1, - args->dotrace) && args->doexit) - /* We cannot start the application. Abort now. */ - _exit (1); -} - - -static inline struct link_map * -find_needed (const char *name) -{ - struct r_scope_elem *scope = &GL(dl_ns)[LM_ID_BASE]._ns_loaded->l_searchlist; - unsigned int n = scope->r_nlist; - - while (n-- > 0) - if (_dl_name_match_p (name, scope->r_list[n])) - return scope->r_list[n]; - - /* Should never happen. */ - return NULL; -} - -static int -match_version (const char *string, struct link_map *map) -{ - const char *strtab = (const void *) D_PTR (map, l_info[DT_STRTAB]); - ElfW(Verdef) *def; - -#define VERDEFTAG (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGIDX (DT_VERDEF)) - if (map->l_info[VERDEFTAG] == NULL) - /* The file has no symbol versioning. */ - return 0; - - def = (ElfW(Verdef) *) ((char *) map->l_addr - + map->l_info[VERDEFTAG]->d_un.d_ptr); - while (1) - { - ElfW(Verdaux) *aux = (ElfW(Verdaux) *) ((char *) def + def->vd_aux); - - /* Compare the version strings. */ - if (strcmp (string, strtab + aux->vda_name) == 0) - /* Bingo! */ - return 1; - - /* If no more definitions we failed to find what we want. */ - if (def->vd_next == 0) - break; - - /* Next definition. */ - def = (ElfW(Verdef) *) ((char *) def + def->vd_next); - } - - return 0; -} - -static bool tls_init_tp_called; - -static void * -init_tls (void) -{ - /* Number of elements in the static TLS block. */ - GL(dl_tls_static_nelem) = GL(dl_tls_max_dtv_idx); - - /* Do not do this twice. The audit interface might have required - the DTV interfaces to be set up early. */ - if (GL(dl_initial_dtv) != NULL) - return NULL; - - /* Allocate the array which contains the information about the - dtv slots. We allocate a few entries more than needed to - avoid the need for reallocation. */ - size_t nelem = GL(dl_tls_max_dtv_idx) + 1 + TLS_SLOTINFO_SURPLUS; - - /* Allocate. */ - GL(dl_tls_dtv_slotinfo_list) = (struct dtv_slotinfo_list *) - calloc (sizeof (struct dtv_slotinfo_list) - + nelem * sizeof (struct dtv_slotinfo), 1); - /* No need to check the return value. If memory allocation failed - the program would have been terminated. */ - - struct dtv_slotinfo *slotinfo = GL(dl_tls_dtv_slotinfo_list)->slotinfo; - GL(dl_tls_dtv_slotinfo_list)->len = nelem; - GL(dl_tls_dtv_slotinfo_list)->next = NULL; - - /* Fill in the information from the loaded modules. No namespace - but the base one can be filled at this time. */ - assert (GL(dl_ns)[LM_ID_BASE + 1]._ns_loaded == NULL); - int i = 0; - for (struct link_map *l = GL(dl_ns)[LM_ID_BASE]._ns_loaded; l != NULL; - l = l->l_next) - if (l->l_tls_blocksize != 0) - { - /* This is a module with TLS data. Store the map reference. - The generation counter is zero. */ - slotinfo[i].map = l; - /* slotinfo[i].gen = 0; */ - ++i; - } - assert (i == GL(dl_tls_max_dtv_idx)); - - /* Compute the TLS offsets for the various blocks. */ - _dl_determine_tlsoffset (); - - /* Construct the static TLS block and the dtv for the initial - thread. For some platforms this will include allocating memory - for the thread descriptor. The memory for the TLS block will - never be freed. It should be allocated accordingly. The dtv - array can be changed if dynamic loading requires it. */ - void *tcbp = _dl_allocate_tls_storage (); - if (tcbp == NULL) - _dl_fatal_printf ("\ -cannot allocate TLS data structures for initial thread"); - - /* Store for detection of the special case by __tls_get_addr - 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. */ - 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; - - return tcbp; -} - -static unsigned int -do_preload (const char *fname, struct link_map *main_map, const char *where) -{ - const char *objname; - const char *err_str = NULL; - struct map_args args; - bool malloced; - - args.str = fname; - args.loader = main_map; - args.mode = __RTLD_SECURE; - - unsigned int old_nloaded = GL(dl_ns)[LM_ID_BASE]._ns_nloaded; - - (void) _dl_catch_error (&objname, &err_str, &malloced, map_doit, &args); - if (__glibc_unlikely (err_str != NULL)) - { - _dl_error_printf ("\ -ERROR: ld.so: object '%s' from %s cannot be preloaded (%s): ignored.\n", - fname, where, err_str); - /* No need to call free, this is still before - the libc's malloc is used. */ - } - else if (GL(dl_ns)[LM_ID_BASE]._ns_nloaded != old_nloaded) - /* It is no duplicate. */ - return 1; - - /* Nothing loaded. */ - return 0; -} - -#if defined SHARED && defined _LIBC_REENTRANT \ - && defined __rtld_lock_default_lock_recursive -static void -rtld_lock_default_lock_recursive (void *lock) -{ - __rtld_lock_default_lock_recursive (lock); -} - -static void -rtld_lock_default_unlock_recursive (void *lock) -{ - __rtld_lock_default_unlock_recursive (lock); -} -#endif - - -static void -security_init (void) -{ - /* Set up the stack checker's canary. */ - uintptr_t stack_chk_guard = _dl_setup_stack_chk_guard (_dl_random); -#ifdef THREAD_SET_STACK_GUARD - THREAD_SET_STACK_GUARD (stack_chk_guard); -#else - __stack_chk_guard = stack_chk_guard; -#endif - - /* Set up the pointer guard as well, if necessary. */ - uintptr_t pointer_chk_guard - = _dl_setup_pointer_guard (_dl_random, stack_chk_guard); -#ifdef THREAD_SET_POINTER_GUARD - THREAD_SET_POINTER_GUARD (pointer_chk_guard); -#endif - __pointer_chk_guard_local = pointer_chk_guard; - - /* We do not need the _dl_random value anymore. The less - information we leave behind, the better, so clear the - variable. */ - _dl_random = NULL; -} - -#include "setup-vdso.h" - -/* The library search path. */ -static const char *library_path attribute_relro; -/* The list preloaded objects. */ -static const char *preloadlist attribute_relro; -/* Nonzero if information about versions has to be printed. */ -static int version_info attribute_relro; - -static void -dl_main (const ElfW(Phdr) *phdr, - ElfW(Word) phnum, - ElfW(Addr) *user_entry, - ElfW(auxv_t) *auxv) -{ - const ElfW(Phdr) *ph; - enum mode mode; - struct link_map *main_map; - size_t file_size; - char *file; - bool has_interp = false; - unsigned int i; - bool prelinked = false; - bool rtld_is_main = false; -#ifndef HP_TIMING_NONAVAIL - hp_timing_t start; - hp_timing_t stop; - hp_timing_t diff; -#endif - void *tcbp = NULL; - - GL(dl_init_static_tls) = &_dl_nothread_init_static_tls; - -#if defined SHARED && defined _LIBC_REENTRANT \ - && defined __rtld_lock_default_lock_recursive - GL(dl_rtld_lock_recursive) = rtld_lock_default_lock_recursive; - GL(dl_rtld_unlock_recursive) = rtld_lock_default_unlock_recursive; -#endif - - /* The explicit initialization here is cheaper than processing the reloc - in the _rtld_local definition's initializer. */ - GL(dl_make_stack_executable_hook) = &_dl_make_stack_executable; - - /* Process the environment variable which control the behaviour. */ - process_envvars (&mode); - -#ifndef HAVE_INLINED_SYSCALLS - /* Set up a flag which tells we are just starting. */ - _dl_starting_up = 1; -#endif - - if (*user_entry == (ElfW(Addr)) ENTRY_POINT) - { - /* Ho ho. We are not the program interpreter! We are the program - itself! This means someone ran ld.so as a command. Well, that - might be convenient to do sometimes. We support it by - interpreting the args like this: - - ld.so PROGRAM ARGS... - - The first argument is the name of a file containing an ELF - executable we will load and run with the following arguments. - To simplify life here, PROGRAM is searched for using the - normal rules for shared objects, rather than $PATH or anything - like that. We just load it and use its entry point; we don't - pay attention to its PT_INTERP command (we are the interpreter - ourselves). This is an easy way to test a new ld.so before - installing it. */ - rtld_is_main = true; - - /* Note the place where the dynamic linker actually came from. */ - GL(dl_rtld_map).l_name = rtld_progname; - - while (_dl_argc > 1) - if (! strcmp (_dl_argv[1], "--list")) - { - mode = list; - GLRO(dl_lazy) = -1; /* This means do no dependency analysis. */ - - ++_dl_skip_args; - --_dl_argc; - ++_dl_argv; - } - else if (! strcmp (_dl_argv[1], "--verify")) - { - mode = verify; - - ++_dl_skip_args; - --_dl_argc; - ++_dl_argv; - } - else if (! strcmp (_dl_argv[1], "--inhibit-cache")) - { - GLRO(dl_inhibit_cache) = 1; - ++_dl_skip_args; - --_dl_argc; - ++_dl_argv; - } - else if (! strcmp (_dl_argv[1], "--library-path") - && _dl_argc > 2) - { - library_path = _dl_argv[2]; - - _dl_skip_args += 2; - _dl_argc -= 2; - _dl_argv += 2; - } - else if (! strcmp (_dl_argv[1], "--inhibit-rpath") - && _dl_argc > 2) - { - GLRO(dl_inhibit_rpath) = _dl_argv[2]; - - _dl_skip_args += 2; - _dl_argc -= 2; - _dl_argv += 2; - } - else if (! strcmp (_dl_argv[1], "--audit") && _dl_argc > 2) - { - process_dl_audit (_dl_argv[2]); - - _dl_skip_args += 2; - _dl_argc -= 2; - _dl_argv += 2; - } - else - break; - - /* If we have no further argument the program was called incorrectly. - Grant the user some education. */ - if (_dl_argc < 2) - _dl_fatal_printf ("\ -Usage: ld.so [OPTION]... EXECUTABLE-FILE [ARGS-FOR-PROGRAM...]\n\ -You have invoked `ld.so', the helper program for shared library executables.\n\ -This program usually lives in the file `/lib/ld.so', and special directives\n\ -in executable files using ELF shared libraries tell the system's program\n\ -loader to load the helper program from this file. This helper program loads\n\ -the shared libraries needed by the program executable, prepares the program\n\ -to run, and runs it. You may invoke this helper program directly from the\n\ -command line to load and run an ELF executable file; this is like executing\n\ -that file itself, but always uses this helper program from the file you\n\ -specified, instead of the helper program file specified in the executable\n\ -file you run. This is mostly of use for maintainers to test new versions\n\ -of this helper program; chances are you did not intend to run this program.\n\ -\n\ - --list list all dependencies and how they are resolved\n\ - --verify verify that given object really is a dynamically linked\n\ - object we can handle\n\ - --inhibit-cache Do not use " LD_SO_CACHE "\n\ - --library-path PATH use given PATH instead of content of the environment\n\ - variable LD_LIBRARY_PATH\n\ - --inhibit-rpath LIST ignore RUNPATH and RPATH information in object names\n\ - in LIST\n\ - --audit LIST use objects named in LIST as auditors\n"); - - ++_dl_skip_args; - --_dl_argc; - ++_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 - so a PT_GNU_STACK with PF_X set means the stack started out with - execute permission. However, this is not really true if the - dynamic linker is the executable the kernel loaded. For this - case, we must reinitialize _dl_stack_flags to match the dynamic - linker itself. If the dynamic linker was built with a - PT_GNU_STACK, then the kernel may have loaded us with a - nonexecutable stack that we will have to make executable when we - load the program below unless it has a PT_GNU_STACK indicating - nonexecutable stack is ok. */ - - for (ph = phdr; ph < &phdr[phnum]; ++ph) - if (ph->p_type == PT_GNU_STACK) - { - GL(dl_stack_flags) = ph->p_flags; - break; - } - - if (__builtin_expect (mode, normal) == verify) - { - const char *objname; - const char *err_str = NULL; - struct map_args args; - bool malloced; - - args.str = rtld_progname; - args.loader = NULL; - args.mode = __RTLD_OPENEXEC; - (void) _dl_catch_error (&objname, &err_str, &malloced, map_doit, - &args); - if (__glibc_unlikely (err_str != NULL)) - /* We don't free the returned string, the programs stops - anyway. */ - _exit (EXIT_FAILURE); - } - else - { - HP_TIMING_NOW (start); - _dl_map_object (NULL, rtld_progname, lt_executable, 0, - __RTLD_OPENEXEC, LM_ID_BASE); - HP_TIMING_NOW (stop); - - HP_TIMING_DIFF (load_time, start, stop); - } - - /* Now the map for the main executable is available. */ - main_map = GL(dl_ns)[LM_ID_BASE]._ns_loaded; - - if (__builtin_expect (mode, normal) == normal - && GL(dl_rtld_map).l_info[DT_SONAME] != NULL - && main_map->l_info[DT_SONAME] != NULL - && strcmp ((const char *) D_PTR (&GL(dl_rtld_map), l_info[DT_STRTAB]) - + GL(dl_rtld_map).l_info[DT_SONAME]->d_un.d_val, - (const char *) D_PTR (main_map, l_info[DT_STRTAB]) - + main_map->l_info[DT_SONAME]->d_un.d_val) == 0) - _dl_fatal_printf ("loader cannot load itself\n"); - - phdr = main_map->l_phdr; - phnum = main_map->l_phnum; - /* We overwrite here a pointer to a malloc()ed string. But since - the malloc() implementation used at this point is the dummy - implementations which has no real free() function it does not - makes sense to free the old string first. */ - main_map->l_name = (char *) ""; - *user_entry = main_map->l_entry; - -#ifdef HAVE_AUX_VECTOR - /* Adjust the on-stack auxiliary vector so that it looks like the - binary was executed directly. */ - for (ElfW(auxv_t) *av = auxv; av->a_type != AT_NULL; av++) - switch (av->a_type) - { - case AT_PHDR: - av->a_un.a_val = (uintptr_t) phdr; - break; - case AT_PHNUM: - av->a_un.a_val = phnum; - break; - case AT_ENTRY: - av->a_un.a_val = *user_entry; - break; - case AT_EXECFN: - av->a_un.a_val = (uintptr_t) _dl_argv[0]; - break; - } -#endif - } - else - { - /* Create a link_map for the executable itself. - This will be what dlopen on "" returns. */ - main_map = _dl_new_object ((char *) "", "", lt_executable, NULL, - __RTLD_OPENEXEC, LM_ID_BASE); - assert (main_map != NULL); - main_map->l_phdr = phdr; - main_map->l_phnum = phnum; - main_map->l_entry = *user_entry; - - /* Even though the link map is not yet fully initialized we can add - it to the map list since there are no possible users running yet. */ - _dl_add_to_namespace_list (main_map, LM_ID_BASE); - assert (main_map == GL(dl_ns)[LM_ID_BASE]._ns_loaded); - - /* At this point we are in a bit of trouble. We would have to - fill in the values for l_dev and l_ino. But in general we - do not know where the file is. We also do not handle AT_EXECFD - even if it would be passed up. - - We leave the values here defined to 0. This is normally no - problem as the program code itself is normally no shared - object and therefore cannot be loaded dynamically. Nothing - prevent the use of dynamic binaries and in these situations - we might get problems. We might not be able to find out - whether the object is already loaded. But since there is no - easy way out and because the dynamic binary must also not - have an SONAME we ignore this program for now. If it becomes - a problem we can force people using SONAMEs. */ - - /* We delay initializing the path structure until we got the dynamic - information for the program. */ - } - - main_map->l_map_end = 0; - main_map->l_text_end = 0; - /* Perhaps the executable has no PT_LOAD header entries at all. */ - main_map->l_map_start = ~0; - /* And it was opened directly. */ - ++main_map->l_direct_opencount; - - /* Scan the program header table for the dynamic section. */ - for (ph = phdr; ph < &phdr[phnum]; ++ph) - switch (ph->p_type) - { - case PT_PHDR: - /* Find out the load address. */ - main_map->l_addr = (ElfW(Addr)) phdr - ph->p_vaddr; - break; - case PT_DYNAMIC: - /* This tells us where to find the dynamic section, - which tells us everything we need to do. */ - main_map->l_ld = (void *) main_map->l_addr + ph->p_vaddr; - break; - case PT_INTERP: - /* This "interpreter segment" was used by the program loader to - find the program interpreter, which is this program itself, the - dynamic linker. We note what name finds us, so that a future - dlopen call or DT_NEEDED entry, for something that wants to link - against the dynamic linker as a shared library, will know that - the shared object is already loaded. */ - _dl_rtld_libname.name = ((const char *) main_map->l_addr - + ph->p_vaddr); - /* _dl_rtld_libname.next = NULL; Already zero. */ - GL(dl_rtld_map).l_libname = &_dl_rtld_libname; - - /* Ordinarilly, we would get additional names for the loader from - our DT_SONAME. This can't happen if we were actually linked as - a static executable (detect this case when we have no DYNAMIC). - If so, assume the filename component of the interpreter path to - be our SONAME, and add it to our name list. */ - if (GL(dl_rtld_map).l_ld == NULL) - { - const char *p = NULL; - const char *cp = _dl_rtld_libname.name; - - /* Find the filename part of the path. */ - while (*cp != '\0') - if (*cp++ == '/') - p = cp; - - if (p != NULL) - { - _dl_rtld_libname2.name = p; - /* _dl_rtld_libname2.next = NULL; Already zero. */ - _dl_rtld_libname.next = &_dl_rtld_libname2; - } - } - - has_interp = true; - break; - case PT_LOAD: - { - ElfW(Addr) mapstart; - ElfW(Addr) allocend; - - /* Remember where the main program starts in memory. */ - mapstart = (main_map->l_addr - + (ph->p_vaddr & ~(GLRO(dl_pagesize) - 1))); - if (main_map->l_map_start > mapstart) - main_map->l_map_start = mapstart; - - /* Also where it ends. */ - allocend = main_map->l_addr + ph->p_vaddr + ph->p_memsz; - if (main_map->l_map_end < allocend) - main_map->l_map_end = allocend; - if ((ph->p_flags & PF_X) && allocend > main_map->l_text_end) - main_map->l_text_end = allocend; - } - break; - - case PT_TLS: - if (ph->p_memsz > 0) - { - /* Note that in the case the dynamic linker we duplicate work - here since we read the PT_TLS entry already in - _dl_start_final. But the result is repeatable so do not - check for this special but unimportant case. */ - main_map->l_tls_blocksize = ph->p_memsz; - main_map->l_tls_align = ph->p_align; - if (ph->p_align == 0) - main_map->l_tls_firstbyte_offset = 0; - else - main_map->l_tls_firstbyte_offset = (ph->p_vaddr - & (ph->p_align - 1)); - main_map->l_tls_initimage_size = ph->p_filesz; - main_map->l_tls_initimage = (void *) ph->p_vaddr; - - /* This image gets the ID one. */ - GL(dl_tls_max_dtv_idx) = main_map->l_tls_modid = 1; - } - break; - - case PT_GNU_STACK: - GL(dl_stack_flags) = ph->p_flags; - break; - - case PT_GNU_RELRO: - main_map->l_relro_addr = ph->p_vaddr; - main_map->l_relro_size = ph->p_memsz; - break; - } - - /* Adjust the address of the TLS initialization image in case - the executable is actually an ET_DYN object. */ - if (main_map->l_tls_initimage != NULL) - main_map->l_tls_initimage - = (char *) main_map->l_tls_initimage + main_map->l_addr; - if (! main_map->l_map_end) - main_map->l_map_end = ~0; - if (! main_map->l_text_end) - main_map->l_text_end = ~0; - if (! GL(dl_rtld_map).l_libname && GL(dl_rtld_map).l_name) - { - /* We were invoked directly, so the program might not have a - PT_INTERP. */ - _dl_rtld_libname.name = GL(dl_rtld_map).l_name; - /* _dl_rtld_libname.next = NULL; Already zero. */ - GL(dl_rtld_map).l_libname = &_dl_rtld_libname; - } - else - assert (GL(dl_rtld_map).l_libname); /* How else did we get here? */ - - /* If the current libname is different from the SONAME, add the - latter as well. */ - if (GL(dl_rtld_map).l_info[DT_SONAME] != NULL - && strcmp (GL(dl_rtld_map).l_libname->name, - (const char *) D_PTR (&GL(dl_rtld_map), l_info[DT_STRTAB]) - + GL(dl_rtld_map).l_info[DT_SONAME]->d_un.d_val) != 0) - { - static struct libname_list newname; - newname.name = ((char *) D_PTR (&GL(dl_rtld_map), l_info[DT_STRTAB]) - + GL(dl_rtld_map).l_info[DT_SONAME]->d_un.d_ptr); - newname.next = NULL; - newname.dont_free = 1; - - assert (GL(dl_rtld_map).l_libname->next == NULL); - GL(dl_rtld_map).l_libname->next = &newname; - } - /* The ld.so must be relocated since otherwise loading audit modules - will fail since they reuse the very same ld.so. */ - assert (GL(dl_rtld_map).l_relocated); - - if (! rtld_is_main) - { - /* Extract the contents of the dynamic section for easy access. */ - elf_get_dynamic_info (main_map, NULL); - /* Set up our cache of pointers into the hash table. */ - _dl_setup_hash (main_map); - } - - if (__builtin_expect (mode, normal) == verify) - { - /* We were called just to verify that this is a dynamic - executable using us as the program interpreter. Exit with an - error if we were not able to load the binary or no interpreter - is specified (i.e., this is no dynamically linked binary. */ - if (main_map->l_ld == NULL) - _exit (1); - - /* We allow here some platform specific code. */ -#ifdef DISTINGUISH_LIB_VERSIONS - DISTINGUISH_LIB_VERSIONS; -#endif - _exit (has_interp ? 0 : 2); - } - - struct link_map **first_preload = &GL(dl_rtld_map).l_next; - /* Set up the data structures for the system-supplied DSO early, - so they can influence _dl_init_paths. */ - setup_vdso (main_map, &first_preload); - -#ifdef DL_SYSDEP_OSCHECK - DL_SYSDEP_OSCHECK (_dl_fatal_printf); -#endif - - /* Initialize the data structures for the search paths for shared - objects. */ - _dl_init_paths (library_path); - - /* Initialize _r_debug. */ - struct r_debug *r = _dl_debug_initialize (GL(dl_rtld_map).l_addr, - LM_ID_BASE); - r->r_state = RT_CONSISTENT; - - /* Put the link_map for ourselves on the chain so it can be found by - name. Note that at this point the global chain of link maps contains - exactly one element, which is pointed to by dl_loaded. */ - if (! GL(dl_rtld_map).l_name) - /* If not invoked directly, the dynamic linker shared object file was - found by the PT_INTERP name. */ - GL(dl_rtld_map).l_name = (char *) GL(dl_rtld_map).l_libname->name; - GL(dl_rtld_map).l_type = lt_library; - main_map->l_next = &GL(dl_rtld_map); - GL(dl_rtld_map).l_prev = main_map; - ++GL(dl_ns)[LM_ID_BASE]._ns_nloaded; - ++GL(dl_load_adds); - - /* If LD_USE_LOAD_BIAS env variable has not been seen, default - to not using bias for non-prelinked PIEs and libraries - and using it for executables or prelinked PIEs or libraries. */ - if (GLRO(dl_use_load_bias) == (ElfW(Addr)) -2) - 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. */ - 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; - - - /* PT_GNU_RELRO is usually the last phdr. */ - size_t cnt = rtld_ehdr->e_phnum; - while (cnt-- > 0) - if (rtld_phdr[cnt].p_type == PT_GNU_RELRO) - { - GL(dl_rtld_map).l_relro_addr = rtld_phdr[cnt].p_vaddr; - GL(dl_rtld_map).l_relro_size = rtld_phdr[cnt].p_memsz; - break; - } - - /* Add the dynamic linker to the TLS list if it also uses TLS. */ - if (GL(dl_rtld_map).l_tls_blocksize != 0) - /* Assign a module ID. Do this before loading any audit modules. */ - GL(dl_rtld_map).l_tls_modid = _dl_next_tls_modid (); - - /* If we have auditing DSOs to load, do it now. */ - if (__glibc_unlikely (audit_list != NULL)) - { - /* Iterate over all entries in the list. The order is important. */ - struct audit_ifaces *last_audit = NULL; - struct audit_list *al = audit_list->next; - - /* Since we start using the auditing DSOs right away we need to - initialize the data structures now. */ - tcbp = init_tls (); - - /* Initialize security features. We need to do it this early - since otherwise the constructors of the audit libraries will - use different values (especially the pointer guard) and will - fail later on. */ - security_init (); - - do - { - int tls_idx = GL(dl_tls_max_dtv_idx); - - /* Now it is time to determine the layout of the static TLS - block and allocate it for the initial thread. Note that we - always allocate the static block, we never defer it even if - no DF_STATIC_TLS bit is set. The reason is that we know - glibc will use the static model. */ - struct dlmopen_args dlmargs; - dlmargs.fname = al->name; - dlmargs.map = NULL; - - const char *objname; - const char *err_str = NULL; - bool malloced; - (void) _dl_catch_error (&objname, &err_str, &malloced, dlmopen_doit, - &dlmargs); - if (__glibc_unlikely (err_str != NULL)) - { - not_loaded: - _dl_error_printf ("\ -ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n", - al->name, err_str); - if (malloced) - free ((char *) err_str); - } - else - { - struct lookup_args largs; - largs.name = "la_version"; - largs.map = dlmargs.map; - - /* Check whether the interface version matches. */ - (void) _dl_catch_error (&objname, &err_str, &malloced, - lookup_doit, &largs); - - unsigned int (*laversion) (unsigned int); - unsigned int lav; - if (err_str == NULL - && (laversion = largs.result) != NULL - && (lav = laversion (LAV_CURRENT)) > 0 - && lav <= LAV_CURRENT) - { - /* Allocate structure for the callback function pointers. - This call can never fail. */ - union - { - struct audit_ifaces ifaces; -#define naudit_ifaces 8 - void (*fptr[naudit_ifaces]) (void); - } *newp = malloc (sizeof (*newp)); - - /* Names of the auditing interfaces. All in one - long string. */ - static const char audit_iface_names[] = - "la_activity\0" - "la_objsearch\0" - "la_objopen\0" - "la_preinit\0" -#if __ELF_NATIVE_CLASS == 32 - "la_symbind32\0" -#elif __ELF_NATIVE_CLASS == 64 - "la_symbind64\0" -#else -# error "__ELF_NATIVE_CLASS must be defined" -#endif -#define STRING(s) __STRING (s) - "la_" STRING (ARCH_LA_PLTENTER) "\0" - "la_" STRING (ARCH_LA_PLTEXIT) "\0" - "la_objclose\0"; - unsigned int cnt = 0; - const char *cp = audit_iface_names; - do - { - largs.name = cp; - (void) _dl_catch_error (&objname, &err_str, &malloced, - lookup_doit, &largs); - - /* Store the pointer. */ - if (err_str == NULL && largs.result != NULL) - { - newp->fptr[cnt] = largs.result; - - /* The dynamic linker link map is statically - allocated, initialize the data now. */ - GL(dl_rtld_map).l_audit[cnt].cookie - = (intptr_t) &GL(dl_rtld_map); - } - else - newp->fptr[cnt] = NULL; - ++cnt; - - cp = (char *) rawmemchr (cp, '\0') + 1; - } - while (*cp != '\0'); - assert (cnt == naudit_ifaces); - - /* Now append the new auditing interface to the list. */ - newp->ifaces.next = NULL; - if (last_audit == NULL) - last_audit = GLRO(dl_audit) = &newp->ifaces; - else - last_audit = last_audit->next = &newp->ifaces; - ++GLRO(dl_naudit); - - /* Mark the DSO as being used for auditing. */ - dlmargs.map->l_auditing = 1; - } - else - { - /* We cannot use the DSO, it does not have the - appropriate interfaces or it expects something - more recent. */ -#ifndef NDEBUG - Lmid_t ns = dlmargs.map->l_ns; -#endif - _dl_close (dlmargs.map); - - /* Make sure the namespace has been cleared entirely. */ - assert (GL(dl_ns)[ns]._ns_loaded == NULL); - assert (GL(dl_ns)[ns]._ns_nloaded == 0); - - GL(dl_tls_max_dtv_idx) = tls_idx; - goto not_loaded; - } - } - - al = al->next; - } - while (al != audit_list->next); - - /* If we have any auditing modules, announce that we already - have two objects loaded. */ - if (__glibc_unlikely (GLRO(dl_naudit) > 0)) - { - struct link_map *ls[2] = { main_map, &GL(dl_rtld_map) }; - - for (unsigned int outer = 0; outer < 2; ++outer) - { - struct audit_ifaces *afct = GLRO(dl_audit); - for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) - { - if (afct->objopen != NULL) - { - ls[outer]->l_audit[cnt].bindflags - = afct->objopen (ls[outer], LM_ID_BASE, - &ls[outer]->l_audit[cnt].cookie); - - ls[outer]->l_audit_any_plt - |= ls[outer]->l_audit[cnt].bindflags != 0; - } - - afct = afct->next; - } - } - } - } - - /* 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. */ - ELF_MACHINE_DEBUG_SETUP (main_map, r); - ELF_MACHINE_DEBUG_SETUP (&GL(dl_rtld_map), r); -#else - if (main_map->l_info[DT_DEBUG] != NULL) - /* There is a DT_DEBUG entry in the dynamic section. Fill it in - with the run-time address of the r_debug structure */ - main_map->l_info[DT_DEBUG]->d_un.d_ptr = (ElfW(Addr)) r; - - /* Fill in the pointer in the dynamic linker's own dynamic section, in - case you run gdb on the dynamic linker directly. */ - if (GL(dl_rtld_map).l_info[DT_DEBUG] != NULL) - GL(dl_rtld_map).l_info[DT_DEBUG]->d_un.d_ptr = (ElfW(Addr)) r; -#endif - - /* We start adding objects. */ - r->r_state = RT_ADD; - _dl_debug_state (); - LIBC_PROBE (init_start, 2, LM_ID_BASE, r); - - /* Auditing checkpoint: we are ready to signal that the initial map - is being constructed. */ - if (__glibc_unlikely (GLRO(dl_naudit) > 0)) - { - struct audit_ifaces *afct = GLRO(dl_audit); - for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) - { - if (afct->activity != NULL) - afct->activity (&main_map->l_audit[cnt].cookie, LA_ACT_ADD); - - afct = afct->next; - } - } - - /* We have two ways to specify objects to preload: via environment - variable and via the file /etc/ld.so.preload. The latter can also - be used when security is enabled. */ - assert (*first_preload == NULL); - struct link_map **preloads = NULL; - unsigned int npreloads = 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 - executable's dependencies and prepended to the global scope - list. If the binary is running setuid all elements - containing a '/' are ignored since it is insecure. */ - char *list = strdupa (preloadlist); - char *p; - - HP_TIMING_NOW (start); - - /* Prevent optimizing strsep. Speed is not important here. */ - while ((p = (strsep) (&list, " :")) != NULL) - if (p[0] != '\0' - && (__builtin_expect (! __libc_enable_secure, 1) - || strchr (p, '/') == NULL)) - npreloads += do_preload (p, main_map, "LD_PRELOAD"); - - HP_TIMING_NOW (stop); - HP_TIMING_DIFF (diff, start, stop); - HP_TIMING_ACCUM_NT (load_time, diff); - } - - /* There usually is no ld.so.preload file, it should only be used - for emergencies and testing. So the open call etc should usually - fail. Using access() on a non-existing file is faster than using - open(). So we do this first. If it succeeds we do almost twice - the work but this does not matter, since it is not for production - use. */ - static const char preload_file[] = "/etc/ld.so.preload"; - 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 (__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 - comments introduced by `#'. */ - char *problem; - char *runp; - size_t rest; - - /* Eliminate comments. */ - runp = file; - rest = file_size; - while (rest > 0) - { - char *comment = memchr (runp, '#', rest); - if (comment == NULL) - break; - - rest -= comment - runp; - do - *comment = ' '; - while (--rest > 0 && *++comment != '\n'); - } - - /* We have one problematic case: if we have a name at the end of - the file without a trailing terminating characters, we cannot - place the \0. Handle the case separately. */ - if (file[file_size - 1] != ' ' && file[file_size - 1] != '\t' - && file[file_size - 1] != '\n' && file[file_size - 1] != ':') - { - problem = &file[file_size]; - while (problem > file && problem[-1] != ' ' - && problem[-1] != '\t' - && problem[-1] != '\n' && problem[-1] != ':') - --problem; - - if (problem > file) - problem[-1] = '\0'; - } - else - { - problem = NULL; - file[file_size - 1] = '\0'; - } - - HP_TIMING_NOW (start); - - if (file != problem) - { - char *p; - runp = file; - while ((p = strsep (&runp, ": \t\n")) != NULL) - if (p[0] != '\0') - npreloads += do_preload (p, main_map, preload_file); - } - - if (problem != NULL) - { - char *p = strndupa (problem, file_size - (problem - file)); - - npreloads += do_preload (p, main_map, preload_file); - } - - HP_TIMING_NOW (stop); - HP_TIMING_DIFF (diff, start, stop); - HP_TIMING_ACCUM_NT (load_time, diff); - - /* We don't need the file anymore. */ - __munmap (file, file_size); - } - } - - if (__glibc_unlikely (*first_preload != NULL)) - { - /* Set up PRELOADS with a vector of the preloaded libraries. */ - struct link_map *l = *first_preload; - preloads = __alloca (npreloads * sizeof preloads[0]); - i = 0; - do - { - preloads[i++] = l; - l = l->l_next; - } while (l); - assert (i == npreloads); - } - - /* Load all the libraries specified by DT_NEEDED entries. If LD_PRELOAD - specified some libraries to load, these are inserted before the actual - dependencies in the executable's searchlist for symbol resolution. */ - HP_TIMING_NOW (start); - _dl_map_object_deps (main_map, preloads, npreloads, mode == trace, 0); - HP_TIMING_NOW (stop); - HP_TIMING_DIFF (diff, start, stop); - HP_TIMING_ACCUM_NT (load_time, diff); - - /* Mark all objects as being in the global scope. */ - for (i = main_map->l_searchlist.r_nlist; i > 0; ) - main_map->l_searchlist.r_list[--i]->l_global = 1; - - /* Remove _dl_rtld_map from the chain. */ - GL(dl_rtld_map).l_prev->l_next = GL(dl_rtld_map).l_next; - if (GL(dl_rtld_map).l_next != NULL) - GL(dl_rtld_map).l_next->l_prev = GL(dl_rtld_map).l_prev; - - for (i = 1; i < main_map->l_searchlist.r_nlist; ++i) - if (main_map->l_searchlist.r_list[i] == &GL(dl_rtld_map)) - break; - - bool rtld_multiple_ref = false; - 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 - chain in symbol search order because gdb uses the chain's order as - its symbol search order. */ - rtld_multiple_ref = true; - - GL(dl_rtld_map).l_prev = main_map->l_searchlist.r_list[i - 1]; - if (__builtin_expect (mode, normal) == normal) - { - GL(dl_rtld_map).l_next = (i + 1 < main_map->l_searchlist.r_nlist - ? main_map->l_searchlist.r_list[i + 1] - : NULL); -#ifdef NEED_DL_SYSINFO_DSO - if (GLRO(dl_sysinfo_map) != NULL - && GL(dl_rtld_map).l_prev->l_next == GLRO(dl_sysinfo_map) - && GL(dl_rtld_map).l_next != GLRO(dl_sysinfo_map)) - GL(dl_rtld_map).l_prev = GLRO(dl_sysinfo_map); -#endif - } - else - /* In trace mode there might be an invisible object (which we - could not find) after the previous one in the search list. - In this case it doesn't matter much where we put the - interpreter object, so we just initialize the list pointer so - that the assertion below holds. */ - GL(dl_rtld_map).l_next = GL(dl_rtld_map).l_prev->l_next; - - assert (GL(dl_rtld_map).l_prev->l_next == GL(dl_rtld_map).l_next); - GL(dl_rtld_map).l_prev->l_next = &GL(dl_rtld_map); - if (GL(dl_rtld_map).l_next != NULL) - { - assert (GL(dl_rtld_map).l_next->l_prev == GL(dl_rtld_map).l_prev); - GL(dl_rtld_map).l_next->l_prev = &GL(dl_rtld_map); - } - } - - /* Now let us see whether all libraries are available in the - versions we need. */ - { - struct version_check_args args; - args.doexit = mode == normal; - args.dotrace = mode == trace; - _dl_receive_error (print_missing_version, version_check_doit, &args); - } - - /* We do not initialize any of the TLS functionality unless any of the - initial modules uses TLS. This makes dynamic loading of modules with - TLS impossible, but to support it requires either eagerly doing setup - now or lazily doing it later. Doing it now makes us incompatible with - an old kernel that can't perform TLS_INIT_TP, even if no TLS is ever - used. Trying to do it lazily is too hairy to try when there could be - multiple threads (from a non-TLS-using libpthread). */ - bool was_tls_init_tp_called = tls_init_tp_called; - if (tcbp == NULL) - tcbp = init_tls (); - - if (__glibc_likely (audit_list == NULL)) - /* Initialize security features. But only if we have not done it - earlier. */ - security_init (); - - if (__builtin_expect (mode, normal) != normal) - { - /* We were run just to list the shared libraries. It is - important that we do this before real relocation, because the - functions we call below for output may no longer work properly - after relocation. */ - struct link_map *l; - - if (GLRO(dl_debug_mask) & DL_DEBUG_PRELINK) - { - struct r_scope_elem *scope = &main_map->l_searchlist; - - for (i = 0; i < scope->r_nlist; i++) - { - l = scope->r_list [i]; - if (l->l_faked) - { - _dl_printf ("\t%s => not found\n", l->l_libname->name); - continue; - } - if (_dl_name_match_p (GLRO(dl_trace_prelink), l)) - GLRO(dl_trace_prelink_map) = l; - _dl_printf ("\t%s => %s (0x%0*Zx, 0x%0*Zx)", - DSO_FILENAME (l->l_libname->name), - DSO_FILENAME (l->l_name), - (int) sizeof l->l_map_start * 2, - (size_t) l->l_map_start, - (int) sizeof l->l_addr * 2, - (size_t) l->l_addr); - - if (l->l_tls_modid) - _dl_printf (" TLS(0x%Zx, 0x%0*Zx)\n", l->l_tls_modid, - (int) sizeof l->l_tls_offset * 2, - (size_t) l->l_tls_offset); - else - _dl_printf ("\n"); - } - } - else if (GLRO(dl_debug_mask) & DL_DEBUG_UNUSED) - { - /* Look through the dependencies of the main executable - and determine which of them is not actually - required. */ - struct link_map *l = main_map; - - /* Relocate the main executable. */ - struct relocate_args args = { .l = l, - .reloc_mode = ((GLRO(dl_lazy) - ? RTLD_LAZY : 0) - | __RTLD_NOIFUNC) }; - _dl_receive_error (print_unresolved, relocate_doit, &args); - - /* This loop depends on the dependencies of the executable to - correspond in number and order to the DT_NEEDED entries. */ - ElfW(Dyn) *dyn = main_map->l_ld; - bool first = true; - while (dyn->d_tag != DT_NULL) - { - if (dyn->d_tag == DT_NEEDED) - { - l = l->l_next; -#ifdef NEED_DL_SYSINFO_DSO - /* Skip the VDSO since it's not part of the list - of objects we brought in via DT_NEEDED entries. */ - if (l == GLRO(dl_sysinfo_map)) - l = l->l_next; -#endif - if (!l->l_used) - { - if (first) - { - _dl_printf ("Unused direct dependencies:\n"); - first = false; - } - - _dl_printf ("\t%s\n", l->l_name); - } - } - - ++dyn; - } - - _exit (first != true); - } - else if (! main_map->l_info[DT_NEEDED]) - _dl_printf ("\tstatically linked\n"); - else - { - for (l = main_map->l_next; l; l = l->l_next) - if (l->l_faked) - /* The library was not found. */ - _dl_printf ("\t%s => not found\n", l->l_libname->name); - else if (strcmp (l->l_libname->name, l->l_name) == 0) - _dl_printf ("\t%s (0x%0*Zx)\n", l->l_libname->name, - (int) sizeof l->l_map_start * 2, - (size_t) l->l_map_start); - else - _dl_printf ("\t%s => %s (0x%0*Zx)\n", l->l_libname->name, - l->l_name, (int) sizeof l->l_map_start * 2, - (size_t) l->l_map_start); - } - - if (__builtin_expect (mode, trace) != trace) - for (i = 1; i < (unsigned int) _dl_argc; ++i) - { - const ElfW(Sym) *ref = NULL; - ElfW(Addr) loadbase; - lookup_t result; - - 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); - - loadbase = LOOKUP_VALUE_ADDRESS (result); - - _dl_printf ("%s found at 0x%0*Zd in object at 0x%0*Zd\n", - _dl_argv[i], - (int) sizeof ref->st_value * 2, - (size_t) ref->st_value, - (int) sizeof loadbase * 2, (size_t) loadbase); - } - else - { - /* If LD_WARN is set, warn about undefined symbols. */ - if (GLRO(dl_lazy) >= 0 && GLRO(dl_verbose)) - { - /* We have to do symbol dependency testing. */ - struct relocate_args args; - unsigned int i; - - args.reloc_mode = ((GLRO(dl_lazy) ? RTLD_LAZY : 0) - | __RTLD_NOIFUNC); - - i = main_map->l_searchlist.r_nlist; - while (i-- > 0) - { - struct link_map *l = main_map->l_initfini[i]; - if (l != &GL(dl_rtld_map) && ! l->l_faked) - { - args.l = l; - _dl_receive_error (print_unresolved, relocate_doit, - &args); - } - } - - if ((GLRO(dl_debug_mask) & DL_DEBUG_PRELINK) - && rtld_multiple_ref) - { - /* Mark the link map as not yet relocated again. */ - GL(dl_rtld_map).l_relocated = 0; - _dl_relocate_object (&GL(dl_rtld_map), - main_map->l_scope, __RTLD_NOIFUNC, 0); - } - } -#define VERNEEDTAG (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGIDX (DT_VERNEED)) - if (version_info) - { - /* Print more information. This means here, print information - about the versions needed. */ - int first = 1; - struct link_map *map; - - for (map = main_map; map != NULL; map = map->l_next) - { - const char *strtab; - ElfW(Dyn) *dyn = map->l_info[VERNEEDTAG]; - ElfW(Verneed) *ent; - - if (dyn == NULL) - continue; - - strtab = (const void *) D_PTR (map, l_info[DT_STRTAB]); - ent = (ElfW(Verneed) *) (map->l_addr + dyn->d_un.d_ptr); - - if (first) - { - _dl_printf ("\n\tVersion information:\n"); - first = 0; - } - - _dl_printf ("\t%s:\n", DSO_FILENAME (map->l_name)); - - while (1) - { - ElfW(Vernaux) *aux; - struct link_map *needed; - - needed = find_needed (strtab + ent->vn_file); - aux = (ElfW(Vernaux) *) ((char *) ent + ent->vn_aux); - - while (1) - { - const char *fname = NULL; - - if (needed != NULL - && match_version (strtab + aux->vna_name, - needed)) - fname = needed->l_name; - - _dl_printf ("\t\t%s (%s) %s=> %s\n", - strtab + ent->vn_file, - strtab + aux->vna_name, - aux->vna_flags & VER_FLG_WEAK - ? "[WEAK] " : "", - fname ?: "not found"); - - if (aux->vna_next == 0) - /* No more symbols. */ - break; - - /* Next symbol. */ - aux = (ElfW(Vernaux) *) ((char *) aux - + aux->vna_next); - } - - if (ent->vn_next == 0) - /* No more dependencies. */ - break; - - /* Next dependency. */ - ent = (ElfW(Verneed) *) ((char *) ent + ent->vn_next); - } - } - } - } - - _exit (0); - } - - if (main_map->l_info[ADDRIDX (DT_GNU_LIBLIST)] - && ! __builtin_expect (GLRO(dl_profile) != NULL, 0) - && ! __builtin_expect (GLRO(dl_dynamic_weak), 0)) - { - ElfW(Lib) *liblist, *liblistend; - struct link_map **r_list, **r_listend, *l; - const char *strtab = (const void *) D_PTR (main_map, l_info[DT_STRTAB]); - - assert (main_map->l_info[VALIDX (DT_GNU_LIBLISTSZ)] != NULL); - liblist = (ElfW(Lib) *) - main_map->l_info[ADDRIDX (DT_GNU_LIBLIST)]->d_un.d_ptr; - liblistend = (ElfW(Lib) *) - ((char *) liblist + - main_map->l_info[VALIDX (DT_GNU_LIBLISTSZ)]->d_un.d_val); - r_list = main_map->l_searchlist.r_list; - r_listend = r_list + main_map->l_searchlist.r_nlist; - - for (; r_list < r_listend && liblist < liblistend; r_list++) - { - l = *r_list; - - if (l == main_map) - continue; - - /* If the library is not mapped where it should, fail. */ - if (l->l_addr) - break; - - /* Next, check if checksum matches. */ - if (l->l_info [VALIDX(DT_CHECKSUM)] == NULL - || l->l_info [VALIDX(DT_CHECKSUM)]->d_un.d_val - != liblist->l_checksum) - break; - - if (l->l_info [VALIDX(DT_GNU_PRELINKED)] == NULL - || l->l_info [VALIDX(DT_GNU_PRELINKED)]->d_un.d_val - != liblist->l_time_stamp) - break; - - if (! _dl_name_match_p (strtab + liblist->l_name, l)) - break; - - ++liblist; - } - - - if (r_list == r_listend && liblist == liblistend) - prelinked = true; - - if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_LIBS)) - _dl_debug_printf ("\nprelink checking: %s\n", - prelinked ? "ok" : "failed"); - } - - - /* Now set up the variable which helps the assembler startup code. */ - GL(dl_ns)[LM_ID_BASE]._ns_main_searchlist = &main_map->l_searchlist; - - /* Save the information about the original global scope list since - we need it in the memory handling later. */ - GLRO(dl_initial_searchlist) = *GL(dl_ns)[LM_ID_BASE]._ns_main_searchlist; - - /* Remember the last search directory added at startup, now that - malloc will no longer be the one from dl-minimal.c. */ - GLRO(dl_init_all_dirs) = GL(dl_all_dirs); - - /* Print scope information. */ - if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_SCOPES)) - { - _dl_debug_printf ("\nInitial object scopes\n"); - - for (struct link_map *l = main_map; l != NULL; l = l->l_next) - _dl_show_scope (l, 0); - } - - if (prelinked) - { - if (main_map->l_info [ADDRIDX (DT_GNU_CONFLICT)] != NULL) - { - ElfW(Rela) *conflict, *conflictend; -#ifndef HP_TIMING_NONAVAIL - hp_timing_t start; - hp_timing_t stop; -#endif - - HP_TIMING_NOW (start); - assert (main_map->l_info [VALIDX (DT_GNU_CONFLICTSZ)] != NULL); - conflict = (ElfW(Rela) *) - main_map->l_info [ADDRIDX (DT_GNU_CONFLICT)]->d_un.d_ptr; - conflictend = (ElfW(Rela) *) - ((char *) conflict - + main_map->l_info [VALIDX (DT_GNU_CONFLICTSZ)]->d_un.d_val); - _dl_resolve_conflicts (main_map, conflict, conflictend); - HP_TIMING_NOW (stop); - HP_TIMING_DIFF (relocate_time, start, stop); - } - - - /* Mark all the objects so we know they have been already relocated. */ - for (struct link_map *l = main_map; l != NULL; l = l->l_next) - { - l->l_relocated = 1; - if (l->l_relro_size) - _dl_protect_relro (l); - - /* Add object to slot information data if necessasy. */ - if (l->l_tls_blocksize != 0 && tls_init_tp_called) - _dl_add_to_slotinfo (l); - } - } - else - { - /* Now we have all the objects loaded. Relocate them all except for - the dynamic linker itself. We do this in reverse order so that copy - relocs of earlier objects overwrite the data written by later - objects. We do not re-relocate the dynamic linker itself in this - loop because that could result in the GOT entries for functions we - call being changed, and that would break us. It is safe to relocate - the dynamic linker out of order because it has no copy relocs (we - know that because it is self-contained). */ - - int consider_profiling = GLRO(dl_profile) != NULL; -#ifndef HP_TIMING_NONAVAIL - hp_timing_t start; - hp_timing_t stop; -#endif - - /* If we are profiling we also must do lazy reloaction. */ - GLRO(dl_lazy) |= consider_profiling; - - HP_TIMING_NOW (start); - unsigned i = main_map->l_searchlist.r_nlist; - while (i-- > 0) - { - struct link_map *l = main_map->l_initfini[i]; - - /* While we are at it, help the memory handling a bit. We have to - mark some data structures as allocated with the fake malloc() - implementation in ld.so. */ - struct libname_list *lnp = l->l_libname->next; - - while (__builtin_expect (lnp != NULL, 0)) - { - lnp->dont_free = 1; - lnp = lnp->next; - } - /* Also allocated with the fake malloc(). */ - l->l_free_initfini = 0; - - if (l != &GL(dl_rtld_map)) - _dl_relocate_object (l, l->l_scope, GLRO(dl_lazy) ? RTLD_LAZY : 0, - consider_profiling); - - /* Add object to slot information data if necessasy. */ - if (l->l_tls_blocksize != 0 && tls_init_tp_called) - _dl_add_to_slotinfo (l); - } - HP_TIMING_NOW (stop); - - HP_TIMING_DIFF (relocate_time, start, stop); - - /* Now enable profiling if needed. Like the previous call, - 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 (__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) - || count_modids != _dl_count_modids ()) - ++GL(dl_tls_generation); - - /* Now that we have completed relocation, the initializer data - for the TLS blocks has its final values and we can copy them - 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 (! tls_init_tp_called) - { - const char *lossage = TLS_INIT_TP (tcbp); - if (__glibc_unlikely (lossage != NULL)) - _dl_fatal_printf ("cannot set up thread-local storage: %s\n", - lossage); - } - - /* Make sure no new search directories have been added. */ - assert (GLRO(dl_init_all_dirs) == GL(dl_all_dirs)); - - if (! prelinked && rtld_multiple_ref) - { - /* There was an explicit ref to the dynamic linker as a shared lib. - Re-relocate ourselves with user-controlled symbol definitions. - - We must do this after TLS initialization in case after this - re-relocation, we might call a user-supplied function - (e.g. calloc from _dl_relocate_object) that uses TLS data. */ - -#ifndef HP_TIMING_NONAVAIL - hp_timing_t start; - hp_timing_t stop; - hp_timing_t add; -#endif - - HP_TIMING_NOW (start); - /* Mark the link map as not yet relocated again. */ - GL(dl_rtld_map).l_relocated = 0; - _dl_relocate_object (&GL(dl_rtld_map), main_map->l_scope, 0, 0); - HP_TIMING_NOW (stop); - HP_TIMING_DIFF (add, start, stop); - HP_TIMING_ACCUM_NT (relocate_time, add); - } - - /* Do any necessary cleanups for the startup OS interface code. - We do these now so that no calls are made after rtld re-relocation - which might be resolved to different functions than we expect. - We cannot do this before relocating the other objects because - _dl_relocate_object might need to call `mprotect' for DT_TEXTREL. */ - _dl_sysdep_start_cleanup (); - -#ifdef SHARED - /* Auditing checkpoint: we have added all objects. */ - 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. */ - if (head->l_auditing == 0) - { - struct audit_ifaces *afct = GLRO(dl_audit); - for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) - { - if (afct->activity != NULL) - afct->activity (&head->l_audit[cnt].cookie, LA_ACT_CONSISTENT); - - afct = afct->next; - } - } - } -#endif - - /* Notify the debugger all new objects are now ready to go. We must re-get - the address since by now the variable might be in another object. */ - r = _dl_debug_initialize (0, LM_ID_BASE); - r->r_state = RT_CONSISTENT; - _dl_debug_state (); - LIBC_PROBE (init_complete, 2, LM_ID_BASE, r); - -#if defined USE_LDCONFIG && !defined MAP_COPY - /* We must munmap() the cache file. */ - _dl_unload_cache (); -#endif - - /* Once we return, _dl_sysdep_start will invoke - the DT_INIT functions and then *USER_ENTRY. */ -} - -/* This is a little helper function for resolving symbols while - tracing the binary. */ -static void -print_unresolved (int errcode __attribute__ ((unused)), const char *objname, - const char *errstring) -{ - if (objname[0] == '\0') - objname = RTLD_PROGNAME; - _dl_error_printf ("%s (%s)\n", errstring, objname); -} - -/* This is a little helper function for resolving symbols while - tracing the binary. */ -static void -print_missing_version (int errcode __attribute__ ((unused)), - const char *objname, const char *errstring) -{ - _dl_error_printf ("%s: %s: %s\n", RTLD_PROGNAME, - objname, errstring); -} - -/* Nonzero if any of the debugging options is enabled. */ -static int any_debug attribute_relro; - -/* Process the string given as the parameter which explains which debugging - options are enabled. */ -static void -process_dl_debug (const char *dl_debug) -{ - /* When adding new entries make sure that the maximal length of a name - is correctly handled in the LD_DEBUG_HELP code below. */ - static const struct - { - unsigned char len; - const char name[10]; - const char helptext[41]; - unsigned short int mask; - } debopts[] = - { -#define LEN_AND_STR(str) sizeof (str) - 1, str - { LEN_AND_STR ("libs"), "display library search paths", - DL_DEBUG_LIBS | DL_DEBUG_IMPCALLS }, - { LEN_AND_STR ("reloc"), "display relocation processing", - DL_DEBUG_RELOC | DL_DEBUG_IMPCALLS }, - { LEN_AND_STR ("files"), "display progress for input file", - DL_DEBUG_FILES | DL_DEBUG_IMPCALLS }, - { LEN_AND_STR ("symbols"), "display symbol table processing", - DL_DEBUG_SYMBOLS | DL_DEBUG_IMPCALLS }, - { LEN_AND_STR ("bindings"), "display information about symbol binding", - DL_DEBUG_BINDINGS | DL_DEBUG_IMPCALLS }, - { LEN_AND_STR ("versions"), "display version dependencies", - DL_DEBUG_VERSIONS | DL_DEBUG_IMPCALLS }, - { LEN_AND_STR ("scopes"), "display scope information", - DL_DEBUG_SCOPES }, - { LEN_AND_STR ("all"), "all previous options combined", - DL_DEBUG_LIBS | DL_DEBUG_RELOC | DL_DEBUG_FILES | DL_DEBUG_SYMBOLS - | DL_DEBUG_BINDINGS | DL_DEBUG_VERSIONS | DL_DEBUG_IMPCALLS - | DL_DEBUG_SCOPES }, - { LEN_AND_STR ("statistics"), "display relocation statistics", - DL_DEBUG_STATISTICS }, - { LEN_AND_STR ("unused"), "determined unused DSOs", - DL_DEBUG_UNUSED }, - { LEN_AND_STR ("help"), "display this help message and exit", - DL_DEBUG_HELP }, - }; -#define ndebopts (sizeof (debopts) / sizeof (debopts[0])) - - /* Skip separating white spaces and commas. */ - while (*dl_debug != '\0') - { - if (*dl_debug != ' ' && *dl_debug != ',' && *dl_debug != ':') - { - size_t cnt; - size_t len = 1; - - while (dl_debug[len] != '\0' && dl_debug[len] != ' ' - && dl_debug[len] != ',' && dl_debug[len] != ':') - ++len; - - for (cnt = 0; cnt < ndebopts; ++cnt) - if (debopts[cnt].len == len - && memcmp (dl_debug, debopts[cnt].name, len) == 0) - { - GLRO(dl_debug_mask) |= debopts[cnt].mask; - any_debug = 1; - break; - } - - if (cnt == ndebopts) - { - /* Display a warning and skip everything until next - separator. */ - char *copy = strndupa (dl_debug, len); - _dl_error_printf ("\ -warning: debug option `%s' unknown; try LD_DEBUG=help\n", copy); - } - - dl_debug += len; - continue; - } - - ++dl_debug; - } - - if (GLRO(dl_debug_mask) & DL_DEBUG_UNUSED) - { - /* In order to get an accurate picture of whether a particular - DT_NEEDED entry is actually used we have to process both - the PLT and non-PLT relocation entries. */ - GLRO(dl_lazy) = 0; - } - - if (GLRO(dl_debug_mask) & DL_DEBUG_HELP) - { - size_t cnt; - - _dl_printf ("\ -Valid options for the LD_DEBUG environment variable are:\n\n"); - - for (cnt = 0; cnt < ndebopts; ++cnt) - _dl_printf (" %.*s%s%s\n", debopts[cnt].len, debopts[cnt].name, - " " + debopts[cnt].len - 3, - debopts[cnt].helptext); - - _dl_printf ("\n\ -To direct the debugging output into a file instead of standard output\n\ -a filename can be specified using the LD_DEBUG_OUTPUT environment variable.\n"); - _exit (0); - } -} - -static void -process_dl_audit (char *str) -{ - /* The parameter is a colon separated list of DSO names. */ - char *p; - - while ((p = (strsep) (&str, ":")) != NULL) - if (p[0] != '\0' - && (__builtin_expect (! __libc_enable_secure, 1) - || strchr (p, '/') == NULL)) - { - /* This is using the local malloc, not the system malloc. The - memory can never be freed. */ - struct audit_list *newp = malloc (sizeof (*newp)); - newp->name = p; - - if (audit_list == NULL) - audit_list = newp->next = newp; - else - { - newp->next = audit_list->next; - audit_list = audit_list->next = newp; - } - } -} - -/* Process all environments variables the dynamic linker must recognize. - Since all of them start with `LD_' we are a bit smarter while finding - all the entries. */ -extern char **_environ attribute_hidden; - - -static void -process_envvars (enum mode *modep) -{ - char **runp = _environ; - char *envline; - enum mode mode = normal; - char *debug_output = NULL; - - /* This is the default place for profiling data file. */ - GLRO(dl_profile_output) - = &"/var/tmp\0/var/profile"[__libc_enable_secure ? 9 : 0]; - - while ((envline = _dl_next_ld_env_entry (&runp)) != NULL) - { - size_t len = 0; - - while (envline[len] != '\0' && envline[len] != '=') - ++len; - - if (envline[len] != '=') - /* This is a "LD_" variable at the end of the string without - a '=' character. Ignore it since otherwise we will access - invalid memory below. */ - continue; - - switch (len) - { - case 4: - /* Warning level, verbose or not. */ - if (memcmp (envline, "WARN", 4) == 0) - GLRO(dl_verbose) = envline[5] != '\0'; - break; - - case 5: - /* Debugging of the dynamic linker? */ - if (memcmp (envline, "DEBUG", 5) == 0) - { - process_dl_debug (&envline[6]); - break; - } - if (memcmp (envline, "AUDIT", 5) == 0) - process_dl_audit (&envline[6]); - break; - - case 7: - /* Print information about versions. */ - if (memcmp (envline, "VERBOSE", 7) == 0) - { - version_info = envline[8] != '\0'; - break; - } - - /* List of objects to be preloaded. */ - if (memcmp (envline, "PRELOAD", 7) == 0) - { - preloadlist = &envline[8]; - break; - } - - /* Which shared object shall be profiled. */ - if (memcmp (envline, "PROFILE", 7) == 0 && envline[8] != '\0') - GLRO(dl_profile) = &envline[8]; - break; - - case 8: - /* Do we bind early? */ - if (memcmp (envline, "BIND_NOW", 8) == 0) - { - GLRO(dl_lazy) = envline[9] == '\0'; - break; - } - if (memcmp (envline, "BIND_NOT", 8) == 0) - GLRO(dl_bind_not) = envline[9] != '\0'; - break; - - case 9: - /* Test whether we want to see the content of the auxiliary - array passed up from the kernel. */ - if (!__libc_enable_secure - && memcmp (envline, "SHOW_AUXV", 9) == 0) - _dl_show_auxv (); - break; - -#if !HAVE_TUNABLES - case 10: - /* Mask for the important hardware capabilities. */ - if (!__libc_enable_secure - && memcmp (envline, "HWCAP_MASK", 10) == 0) - GLRO(dl_hwcap_mask) = __strtoul_internal (&envline[11], NULL, - 0, 0); - break; -#endif - - case 11: - /* Path where the binary is found. */ - if (!__libc_enable_secure - && memcmp (envline, "ORIGIN_PATH", 11) == 0) - GLRO(dl_origin_path) = &envline[12]; - break; - - case 12: - /* The library search path. */ - if (memcmp (envline, "LIBRARY_PATH", 12) == 0) - { - library_path = &envline[13]; - break; - } - - /* Where to place the profiling data file. */ - if (memcmp (envline, "DEBUG_OUTPUT", 12) == 0) - { - debug_output = &envline[13]; - break; - } - - if (!__libc_enable_secure - && memcmp (envline, "DYNAMIC_WEAK", 12) == 0) - GLRO(dl_dynamic_weak) = 1; - break; - - case 13: - /* We might have some extra environment variable with length 13 - to handle. */ -#ifdef EXTRA_LD_ENVVARS_13 - EXTRA_LD_ENVVARS_13 -#endif - if (!__libc_enable_secure - && memcmp (envline, "USE_LOAD_BIAS", 13) == 0) - { - GLRO(dl_use_load_bias) = envline[14] == '1' ? -1 : 0; - break; - } - break; - - case 14: - /* Where to place the profiling data file. */ - if (!__libc_enable_secure - && memcmp (envline, "PROFILE_OUTPUT", 14) == 0 - && envline[15] != '\0') - GLRO(dl_profile_output) = &envline[15]; - break; - - case 16: - /* The mode of the dynamic linker can be set. */ - if (memcmp (envline, "TRACE_PRELINKING", 16) == 0) - { - mode = trace; - GLRO(dl_verbose) = 1; - GLRO(dl_debug_mask) |= DL_DEBUG_PRELINK; - GLRO(dl_trace_prelink) = &envline[17]; - } - break; - - case 20: - /* The mode of the dynamic linker can be set. */ - if (memcmp (envline, "TRACE_LOADED_OBJECTS", 20) == 0) - mode = trace; - break; - - /* We might have some extra environment variable to handle. This - is tricky due to the pre-processing of the length of the name - in the switch statement here. The code here assumes that added - environment variables have a different length. */ -#ifdef EXTRA_LD_ENVVARS - EXTRA_LD_ENVVARS -#endif - } - } - - /* The caller wants this information. */ - *modep = mode; - - /* Extra security for SUID binaries. Remove all dangerous environment - variables. */ - if (__builtin_expect (__libc_enable_secure, 0)) - { - static const char unsecure_envvars[] = -#ifdef EXTRA_UNSECURE_ENVVARS - EXTRA_UNSECURE_ENVVARS -#endif - UNSECURE_ENVVARS; - const char *nextp; - - nextp = unsecure_envvars; - do - { - unsetenv (nextp); - /* We could use rawmemchr but this need not be fast. */ - nextp = (char *) (strchr) (nextp, '\0') + 1; - } - while (*nextp != '\0'); - - if (__access ("/etc/suid-debug", F_OK) != 0) - { -#if !HAVE_TUNABLES - unsetenv ("MALLOC_CHECK_"); -#endif - GLRO(dl_debug_mask) = 0; - } - - if (mode != normal) - _exit (5); - } - /* If we have to run the dynamic linker in debugging mode and the - LD_DEBUG_OUTPUT environment variable is given, we write the debug - messages to this file. */ - else if (any_debug && debug_output != NULL) - { - const int flags = O_WRONLY | O_APPEND | O_CREAT | O_NOFOLLOW; - size_t name_len = strlen (debug_output); - char buf[name_len + 12]; - char *startp; - - buf[name_len + 11] = '\0'; - startp = _itoa (__getpid (), &buf[name_len + 11], 10, 0); - *--startp = '.'; - startp = memcpy (startp - name_len, debug_output, name_len); - - GLRO(dl_debug_fd) = __open (startp, flags, DEFFILEMODE); - if (GLRO(dl_debug_fd) == -1) - /* We use standard output if opening the file failed. */ - GLRO(dl_debug_fd) = STDOUT_FILENO; - } -} - - -/* Print the various times we collected. */ -static void -__attribute ((noinline)) -print_statistics (hp_timing_t *rtld_total_timep) -{ -#ifndef HP_TIMING_NONAVAIL - char buf[200]; - char *cp; - char *wp; - - /* Total time rtld used. */ - if (HP_SMALL_TIMING_AVAIL) - { - HP_TIMING_PRINT (buf, sizeof (buf), *rtld_total_timep); - _dl_debug_printf ("\nruntime linker statistics:\n" - " total startup time in dynamic loader: %s\n", buf); - - /* Print relocation statistics. */ - char pbuf[30]; - HP_TIMING_PRINT (buf, sizeof (buf), relocate_time); - cp = _itoa ((1000ULL * relocate_time) / *rtld_total_timep, - pbuf + sizeof (pbuf), 10, 0); - wp = pbuf; - switch (pbuf + sizeof (pbuf) - cp) - { - case 3: - *wp++ = *cp++; - case 2: - *wp++ = *cp++; - case 1: - *wp++ = '.'; - *wp++ = *cp++; - } - *wp = '\0'; - _dl_debug_printf ("\ - time needed for relocation: %s (%s%%)\n", buf, pbuf); - } -#endif - - unsigned long int num_relative_relocations = 0; - for (Lmid_t ns = 0; ns < GL(dl_nns); ++ns) - { - if (GL(dl_ns)[ns]._ns_loaded == NULL) - continue; - - struct r_scope_elem *scope = &GL(dl_ns)[ns]._ns_loaded->l_searchlist; - - for (unsigned int i = 0; i < scope->r_nlist; i++) - { - struct link_map *l = scope->r_list [i]; - - if (l->l_addr != 0 && l->l_info[VERSYMIDX (DT_RELCOUNT)]) - num_relative_relocations - += l->l_info[VERSYMIDX (DT_RELCOUNT)]->d_un.d_val; -#ifndef ELF_MACHINE_REL_RELATIVE - /* Relative relocations are processed on these architectures if - library is loaded to different address than p_vaddr or - if not prelinked. */ - if ((l->l_addr != 0 || !l->l_info[VALIDX(DT_GNU_PRELINKED)]) - && l->l_info[VERSYMIDX (DT_RELACOUNT)]) -#else - /* On e.g. IA-64 or Alpha, relative relocations are processed - only if library is loaded to different address than p_vaddr. */ - if (l->l_addr != 0 && l->l_info[VERSYMIDX (DT_RELACOUNT)]) -#endif - num_relative_relocations - += l->l_info[VERSYMIDX (DT_RELACOUNT)]->d_un.d_val; - } - } - - _dl_debug_printf (" number of relocations: %lu\n" - " number of relocations from cache: %lu\n" - " number of relative relocations: %lu\n", - GL(dl_num_relocations), - GL(dl_num_cache_relocations), - num_relative_relocations); - -#ifndef HP_TIMING_NONAVAIL - /* Time spend while loading the object and the dependencies. */ - if (HP_SMALL_TIMING_AVAIL) - { - char pbuf[30]; - HP_TIMING_PRINT (buf, sizeof (buf), load_time); - cp = _itoa ((1000ULL * load_time) / *rtld_total_timep, - pbuf + sizeof (pbuf), 10, 0); - wp = pbuf; - switch (pbuf + sizeof (pbuf) - cp) - { - case 3: - *wp++ = *cp++; - case 2: - *wp++ = *cp++; - case 1: - *wp++ = '.'; - *wp++ = *cp++; - } - *wp = '\0'; - _dl_debug_printf ("\ - time needed to load objects: %s (%s%%)\n", - buf, pbuf); - } -#endif -} diff --git a/elf/setup-vdso.h b/elf/setup-vdso.h deleted file mode 100644 index 2db597eba3..0000000000 --- a/elf/setup-vdso.h +++ /dev/null @@ -1,121 +0,0 @@ -/* Set up the data structures for the system-supplied DSO. - Copyright (C) 2012-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -static inline void __attribute__ ((always_inline)) -setup_vdso (struct link_map *main_map __attribute__ ((unused)), - struct link_map ***first_preload __attribute__ ((unused))) -{ -#ifdef NEED_DL_SYSINFO_DSO - if (GLRO(dl_sysinfo_dso) == NULL) - return; - - /* Do an abridged version of the work _dl_map_object_from_fd would do - to map in the object. It's already mapped and prelinked (and - better be, since it's read-only and so we couldn't relocate it). - We just want our data structures to describe it as if we had just - mapped and relocated it normally. */ - struct link_map *l = _dl_new_object ((char *) "", "", lt_library, NULL, - 0, LM_ID_BASE); - if (__glibc_likely (l != NULL)) - { - static ElfW(Dyn) dyn_temp[DL_RO_DYN_TEMP_CNT] attribute_relro; - - l->l_phdr = ((const void *) GLRO(dl_sysinfo_dso) - + GLRO(dl_sysinfo_dso)->e_phoff); - l->l_phnum = GLRO(dl_sysinfo_dso)->e_phnum; - for (uint_fast16_t i = 0; i < l->l_phnum; ++i) - { - const ElfW(Phdr) *const ph = &l->l_phdr[i]; - if (ph->p_type == PT_DYNAMIC) - { - l->l_ld = (void *) ph->p_vaddr; - l->l_ldnum = ph->p_memsz / sizeof (ElfW(Dyn)); - } - else if (ph->p_type == PT_LOAD) - { - if (! l->l_addr) - l->l_addr = ph->p_vaddr; - if (ph->p_vaddr + ph->p_memsz >= l->l_map_end) - l->l_map_end = ph->p_vaddr + ph->p_memsz; - if ((ph->p_flags & PF_X) - && ph->p_vaddr + ph->p_memsz >= l->l_text_end) - l->l_text_end = ph->p_vaddr + ph->p_memsz; - } - else - /* There must be no TLS segment. */ - assert (ph->p_type != PT_TLS); - } - l->l_map_start = (ElfW(Addr)) GLRO(dl_sysinfo_dso); - l->l_addr = l->l_map_start - l->l_addr; - l->l_map_end += l->l_addr; - l->l_text_end += l->l_addr; - l->l_ld = (void *) ((ElfW(Addr)) l->l_ld + l->l_addr); - elf_get_dynamic_info (l, dyn_temp); - _dl_setup_hash (l); - l->l_relocated = 1; - - /* The vDSO is always used. */ - l->l_used = 1; - - /* Initialize l_local_scope to contain just this map. This allows - the use of dl_lookup_symbol_x to resolve symbols within the vdso. - So we create a single entry list pointing to l_real as its only - element */ - l->l_local_scope[0]->r_nlist = 1; - l->l_local_scope[0]->r_list = &l->l_real; - - /* Now that we have the info handy, use the DSO image's soname - so this object can be looked up by name. Note that we do not - set l_name here. That field gives the file name of the DSO, - and this DSO is not associated with any file. */ - if (l->l_info[DT_SONAME] != NULL) - { - /* Work around a kernel problem. The kernel cannot handle - addresses in the vsyscall DSO pages in writev() calls. */ - const char *dsoname = ((char *) D_PTR (l, l_info[DT_STRTAB]) - + l->l_info[DT_SONAME]->d_un.d_val); - size_t len = strlen (dsoname) + 1; - char *copy = malloc (len); - if (copy == NULL) - _dl_fatal_printf ("out of memory\n"); - l->l_libname->name = l->l_name = memcpy (copy, dsoname, len); - } - - /* Add the vDSO to the object list. */ - _dl_add_to_namespace_list (l, LM_ID_BASE); - -# 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); - GL(dl_rtld_map).l_next = l; - l->l_prev = &GL(dl_rtld_map); - *first_preload = &l->l_next; -# else - GL(dl_nns) = 1; -# endif - - /* We have a prelinked DSO preloaded by the system. */ - GLRO(dl_sysinfo_map) = l; -# ifdef NEED_DL_SYSINFO - if (GLRO(dl_sysinfo) == DL_SYSINFO_DEFAULT) - GLRO(dl_sysinfo) = GLRO(dl_sysinfo_dso)->e_entry + l->l_addr; -# endif - } -#endif -} diff --git a/elf/sln.c b/elf/sln.c deleted file mode 100644 index af2d0de164..0000000000 --- a/elf/sln.c +++ /dev/null @@ -1,202 +0,0 @@ -/* `sln' program to create symbolic links between files. - Copyright (C) 1998-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -#include <error.h> -#include <errno.h> -#include <libintl.h> -#include <locale.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <unistd.h> -#include <errno.h> -#include <ctype.h> -#include <stdio.h> -#include <string.h> -#include <limits.h> - -#include "../version.h" - -#define PACKAGE _libc_intl_domainname - -static int makesymlink (const char *src, const char *dest); -static int makesymlinks (const char *file); -static void usage (void); - -int -main (int argc, char **argv) -{ - /* Set locale via LC_ALL. */ - setlocale (LC_ALL, ""); - - /* Set the text message domain. */ - textdomain (PACKAGE); - - switch (argc) - { - case 2: - if (strcmp (argv[1], "--version") == 0) { - printf ("sln %s%s\n", PKGVERSION, VERSION); - return 0; - } else if (strcmp (argv[1], "--help") == 0) { - usage (); - return 0; - } - return makesymlinks (argv [1]); - break; - - case 3: - return makesymlink (argv [1], argv [2]); - break; - - default: - usage (); - return 1; - break; - } -} - -static void -usage (void) -{ - printf (_("Usage: sln src dest|file\n\n")); - printf (_("For bug reporting instructions, please see:\n\ -%s.\n"), REPORT_BUGS_TO); -} - -static int -makesymlinks (const char *file) -{ - char *buffer = NULL; - size_t bufferlen = 0; - int ret; - int lineno; - FILE *fp; - - if (strcmp (file, "-") == 0) - fp = stdin; - else - { - fp = fopen (file, "r"); - if (fp == NULL) - { - fprintf (stderr, _("%s: file open error: %m\n"), file); - return 1; - } - } - - ret = 0; - lineno = 0; - while (!feof_unlocked (fp)) - { - ssize_t n = getline (&buffer, &bufferlen, fp); - char *src; - char *dest; - char *cp = buffer; - - if (n < 0) - break; - if (buffer[n - 1] == '\n') - buffer[n - 1] = '\0'; - - ++lineno; - while (isspace (*cp)) - ++cp; - if (*cp == '\0') - /* Ignore empty lines. */ - continue; - src = cp; - - do - ++cp; - while (*cp != '\0' && ! isspace (*cp)); - if (*cp != '\0') - *cp++ = '\0'; - - while (isspace (*cp)) - ++cp; - if (*cp == '\0') - { - fprintf (stderr, _("No target in line %d\n"), lineno); - ret = 1; - continue; - } - dest = cp; - - do - ++cp; - while (*cp != '\0' && ! isspace (*cp)); - if (*cp != '\0') - *cp++ = '\0'; - - ret |= makesymlink (src, dest); - } - fclose (fp); - - return ret; -} - -static int -makesymlink (const char *src, const char *dest) -{ - struct stat64 stats; - const char *error; - - /* Destination must not be a directory. */ - if (lstat64 (dest, &stats) == 0) - { - if (S_ISDIR (stats.st_mode)) - { - fprintf (stderr, _("%s: destination must not be a directory\n"), - dest); - return 1; - } - else if (unlink (dest) && errno != ENOENT) - { - fprintf (stderr, _("%s: failed to remove the old destination\n"), - dest); - return 1; - } - } - else if (errno != ENOENT) - { - error = strerror (errno); - fprintf (stderr, _("%s: invalid destination: %s\n"), dest, error); - return -1; - } - - if (symlink (src, dest) == 0) - { - /* Destination must exist by now. */ - if (access (dest, F_OK)) - { - error = strerror (errno); - unlink (dest); - fprintf (stderr, _("Invalid link from \"%s\" to \"%s\": %s\n"), - src, dest, error); - return 1; - } - return 0; - } - else - { - error = strerror (errno); - fprintf (stderr, _("Invalid link from \"%s\" to \"%s\": %s\n"), - src, dest, error); - return 1; - } -} diff --git a/elf/sofini.c b/elf/sofini.c deleted file mode 100644 index 13e74b7903..0000000000 --- a/elf/sofini.c +++ /dev/null @@ -1,19 +0,0 @@ -/* Finalizer module for ELF shared C library. This provides terminating - null pointer words in the `.ctors' and `.dtors' sections. */ - -#ifndef NO_CTORS_DTORS_SECTIONS -static void (*const __CTOR_END__[1]) (void) - __attribute__ ((used, section (".ctors"))) - = { 0 }; -static void (*const __DTOR_END__[1]) (void) - __attribute__ ((used, section (".dtors"))) - = { 0 }; -#endif - -/* Terminate the frame unwind info section with a 4byte 0 as a sentinel; - this would be the 'length' field in a real FDE. */ - -typedef unsigned int ui32 __attribute__ ((mode (SI))); -static const ui32 __FRAME_END__[1] - __attribute__ ((used, section (".eh_frame"))) - = { 0 }; diff --git a/elf/soinit.c b/elf/soinit.c deleted file mode 100644 index fe9935732b..0000000000 --- a/elf/soinit.c +++ /dev/null @@ -1,43 +0,0 @@ -/* Initializer module for building the ELF shared C library. This file and - sofini.c do the work normally done by crtbeginS.o and crtendS.o, to wrap - the `.ctors' and `.dtors' sections so the lists are terminated, and - calling those lists of functions. */ - -#ifndef NO_CTORS_DTORS_SECTIONS -# include <stdlib.h> - -static void (*const __CTOR_LIST__[1]) (void) - __attribute__ ((used, section (".ctors"))) - = { (void (*) (void)) -1 }; -static void (*const __DTOR_LIST__[1]) (void) - __attribute__ ((used, section (".dtors"))) - = { (void (*) (void)) -1 }; - -static inline void -run_hooks (void (*const list[]) (void)) -{ - while (*++list) - (**list) (); -} - -/* This function will be called from _init in init-first.c. */ -void -__libc_global_ctors (void) -{ - /* Call constructor functions. */ - run_hooks (__CTOR_LIST__); -} - - -/* This function becomes the DT_FINI termination function - for the C library. */ -void -__libc_fini (void) -{ - /* Call destructor functions. */ - run_hooks (__DTOR_LIST__); -} - -void (*_fini_ptr) (void) __attribute__ ((section (".fini_array"))) - = &__libc_fini; -#endif diff --git a/elf/sotruss-lib.c b/elf/sotruss-lib.c deleted file mode 100644 index da2fedd52a..0000000000 --- a/elf/sotruss-lib.c +++ /dev/null @@ -1,386 +0,0 @@ -/* Trace calls through PLTs and show caller, callee, and parameters. - Copyright (C) 2011-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Ulrich Drepper <drepper@gmail.com>, 2011. - - 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 <error.h> -#include <fcntl.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <sys/param.h> -#include <sys/uio.h> - -#include <ldsodefs.h> - - -extern const char *__progname; -extern const char *__progname_full; - - -/* List of objects to trace calls from. */ -static const char *fromlist; -/* List of objects to trace calls to. */ -static const char *tolist; - -/* If non-zero, also trace returns of the calls. */ -static int do_exit; -/* If non-zero print PID for each line. */ -static int print_pid; - -/* The output stream to use. */ -static FILE *out_file; - - -static int -match_pid (pid_t pid, const char *which) -{ - if (which == NULL || which[0] == '\0') - { - print_pid = 1; - return 1; - } - - char *endp; - unsigned long n = strtoul (which, &endp, 0); - return *endp == '\0' && n == pid; -} - - -static void -init (void) -{ - fromlist = getenv ("SOTRUSS_FROMLIST"); - if (fromlist != NULL && fromlist[0] == '\0') - fromlist = NULL; - tolist = getenv ("SOTRUSS_TOLIST"); - if (tolist != NULL && tolist[0] == '\0') - tolist = NULL; - do_exit = (getenv ("SOTRUSS_EXIT") ?: "")[0] != '\0'; - - /* Determine whether this process is supposed to be traced and if - yes, whether we should print into a file. */ - const char *which_process = getenv ("SOTRUSS_WHICH"); - pid_t pid = getpid (); - int out_fd = -1; - if (match_pid (pid, which_process)) - { - const char *out_filename = getenv ("SOTRUSS_OUTNAME"); - - if (out_filename != NULL && out_filename[0] != 0) - { - size_t out_filename_len = strlen (out_filename) + 13; - char fullname[out_filename_len]; - char *endp = stpcpy (fullname, out_filename); - if (which_process == NULL || which_process[0] == '\0') - snprintf (endp, 13, ".%ld", (long int) pid); - - out_fd = open (fullname, O_RDWR | O_CREAT | O_TRUNC, 0666); - if (out_fd != -1) - print_pid = 0; - } - } - - /* If we do not write into a file write to stderr. Duplicate the - descriptor so that we can keep printing in case the program - closes stderr. Try first to allocate a descriptor with a value - usually not used as to minimize interference with the - program. */ - if (out_fd == -1) - { - out_fd = fcntl (STDERR_FILENO, F_DUPFD, 1000); - if (out_fd == -1) - out_fd = dup (STDERR_FILENO); - } - - if (out_fd != -1) - { - /* Convert file descriptor into a stream. */ - out_file = fdopen (out_fd, "w"); - if (out_file != NULL) - setlinebuf (out_file); - } -} - - -/* Audit interface verification. We also initialize everything if - everything checks out OK. */ -unsigned int -la_version (unsigned int v) -{ - if (v != LAV_CURRENT) - error (1, 0, "cannot handle interface version %u", v); - - init (); - - return v; -} - - -/* Check whether a file name is on the colon-separated list of file - names. */ -static unsigned int -match_file (const char *list, const char *name, size_t name_len, - unsigned int mask) -{ - if (list[0] == '\0') - return 0; - - const char *cp = list; - while (1) - { - if (strncmp (cp, name, name_len) == 0 - && (cp[name_len] == ':' || cp[name_len] == '\0')) - return mask; - - cp = strchr (cp, ':'); - if (cp == NULL) - return 0; - ++cp; - } -} - - -unsigned int -la_objopen (struct link_map *map, Lmid_t lmid, uintptr_t *cookie) -{ - if (out_file == NULL) - return 0; - - const char *full_name = map->l_name ?: ""; - if (full_name[0] == '\0') - full_name = __progname_full; - size_t full_name_len = strlen (full_name); - const char *base_name = basename (full_name); - if (base_name[0] == '\0') - base_name = __progname; - size_t base_name_len = strlen (base_name); - - int result = 0; - const char *print_name = NULL; - for (struct libname_list *l = map->l_libname; l != NULL; l = l->next) - { - if (print_name == NULL || (print_name[0] == '/' && l->name[0] != '/')) - print_name = l->name; - - if (fromlist != NULL) - result |= match_file (fromlist, l->name, strlen (l->name), - LA_FLG_BINDFROM); - - if (tolist != NULL) - result |= match_file (tolist, l->name, strlen (l->name),LA_FLG_BINDTO); - } - - if (print_name == NULL) - print_name = base_name; - if (print_name[0] == '\0') - print_name = __progname; - - /* We cannot easily get to the object name in the PLT handling - functions. Use the cookie to get the string pointer passed back - to us. */ - *cookie = (uintptr_t) print_name; - - /* The object name has to be on the list of objects to trace calls - from or that list must be empty. In the latter case we trace - only calls from the main binary. */ - if (fromlist == NULL) - result |= map->l_name[0] == '\0' ? LA_FLG_BINDFROM : 0; - else - result |= (match_file (fromlist, full_name, full_name_len, - LA_FLG_BINDFROM) - | match_file (fromlist, base_name, base_name_len, - LA_FLG_BINDFROM)); - - /* The object name has to be on the list of objects to trace calls - to or that list must be empty. In the latter case we trace - calls toall objects. */ - if (tolist == NULL) - result |= LA_FLG_BINDTO; - else - result |= (match_file (tolist, full_name, full_name_len, LA_FLG_BINDTO) - | match_file (tolist, base_name, base_name_len, LA_FLG_BINDTO)); - - return result; -} - - -#if __ELF_NATIVE_CLASS == 32 -# define la_symbind la_symbind32 -typedef Elf32_Sym Elf_Sym; -#else -# define la_symbind la_symbind64 -typedef Elf64_Sym Elf_Sym; -#endif - -uintptr_t -la_symbind (Elf_Sym *sym, unsigned int ndx, uintptr_t *refcook, - uintptr_t *defcook, unsigned int *flags, const char *symname) -{ - if (!do_exit) - *flags = LA_SYMB_NOPLTEXIT; - - return sym->st_value; -} - - -static void -print_enter (uintptr_t *refcook, uintptr_t *defcook, const char *symname, - unsigned long int reg1, unsigned long int reg2, - unsigned long int reg3, unsigned int flags) -{ - char buf[3 * sizeof (pid_t) + 3]; - buf[0] = '\0'; - if (print_pid) - snprintf (buf, sizeof (buf), "%5ld: ", (long int) getpid ()); - - fprintf (out_file, "%s%15s -> %-15s:%s%s(0x%lx, 0x%lx, 0x%lx)\n", - buf, (char *) *refcook, (char *) *defcook, - (flags & LA_SYMB_NOPLTEXIT) ? "*" : " ", symname, reg1, reg2, reg3); -} - - -#ifdef __i386__ -Elf32_Addr -la_i86_gnu_pltenter (Elf32_Sym *sym __attribute__ ((unused)), - unsigned int ndx __attribute__ ((unused)), - uintptr_t *refcook, uintptr_t *defcook, - La_i86_regs *regs, unsigned int *flags, - const char *symname, long int *framesizep) -{ - unsigned long int *sp = (unsigned long int *) regs->lr_esp; - - print_enter (refcook, defcook, symname, sp[1], sp[2], sp[3], *flags); - - /* No need to copy anything, we will not need the parameters in any case. */ - *framesizep = 0; - - return sym->st_value; -} -#elif defined __x86_64__ -Elf64_Addr -la_x86_64_gnu_pltenter (Elf64_Sym *sym __attribute__ ((unused)), - unsigned int ndx __attribute__ ((unused)), - uintptr_t *refcook, uintptr_t *defcook, - La_x86_64_regs *regs, unsigned int *flags, - const char *symname, long int *framesizep) -{ - print_enter (refcook, defcook, symname, - regs->lr_rdi, regs->lr_rsi, regs->lr_rdx, *flags); - - /* No need to copy anything, we will not need the parameters in any case. */ - *framesizep = 0; - - return sym->st_value; -} -#elif defined __sparc__ && !defined __arch64__ -Elf32_Addr -la_sparc32_gnu_pltenter (Elf32_Sym *sym __attribute__ ((unused)), - unsigned int ndx __attribute__ ((unused)), - uintptr_t *refcook, uintptr_t *defcook, - La_sparc32_regs *regs, unsigned int *flags, - const char *symname, long int *framesizep) -{ - print_enter (refcook, defcook, symname, - regs->lr_reg[0], regs->lr_reg[1], regs->lr_reg[2], - *flags); - - /* No need to copy anything, we will not need the parameters in any case. */ - *framesizep = 0; - - return sym->st_value; -} -#elif defined __sparc__ && defined __arch64__ -Elf64_Addr -la_sparc64_gnu_pltenter (Elf64_Sym *sym __attribute__ ((unused)), - unsigned int ndx __attribute__ ((unused)), - uintptr_t *refcook, uintptr_t *defcook, - La_sparc64_regs *regs, unsigned int *flags, - const char *symname, long int *framesizep) -{ - print_enter (refcook, defcook, symname, - regs->lr_reg[0], regs->lr_reg[1], regs->lr_reg[2], - *flags); - - /* No need to copy anything, we will not need the parameters in any case. */ - *framesizep = 0; - - return sym->st_value; -} -#elif !defined HAVE_ARCH_PLTENTER -# warning "pltenter for architecture not supported" -#endif - - -static void -print_exit (uintptr_t *refcook, uintptr_t *defcook, const char *symname, - unsigned long int reg) -{ - char buf[3 * sizeof (pid_t) + 3]; - buf[0] = '\0'; - if (print_pid) - snprintf (buf, sizeof (buf), "%5ld: ", (long int) getpid ()); - - fprintf (out_file, "%s%15s -> %-15s:%s%s - 0x%lx\n", - buf, (char *) *refcook, (char *) *defcook, " ", symname, reg); -} - - -#ifdef __i386__ -unsigned int -la_i86_gnu_pltexit (Elf32_Sym *sym, unsigned int ndx, uintptr_t *refcook, - uintptr_t *defcook, const struct La_i86_regs *inregs, - struct La_i86_retval *outregs, const char *symname) -{ - print_exit (refcook, defcook, symname, outregs->lrv_eax); - - return 0; -} -#elif defined __x86_64__ -unsigned int -la_x86_64_gnu_pltexit (Elf64_Sym *sym, unsigned int ndx, uintptr_t *refcook, - uintptr_t *defcook, const struct La_x86_64_regs *inregs, - struct La_x86_64_retval *outregs, const char *symname) -{ - print_exit (refcook, defcook, symname, outregs->lrv_rax); - - return 0; -} -#elif defined __sparc__ && !defined __arch64__ -unsigned int -la_sparc32_gnu_pltexit (Elf32_Sym *sym, unsigned int ndx, uintptr_t *refcook, - uintptr_t *defcook, const struct La_sparc32_regs *inregs, - struct La_sparc32_retval *outregs, const char *symname) -{ - print_exit (refcook, defcook, symname, outregs->lrv_reg[0]); - - return 0; -} -#elif defined __sparc__ && defined __arch64__ -unsigned int -la_sparc64_gnu_pltexit (Elf64_Sym *sym, unsigned int ndx, uintptr_t *refcook, - uintptr_t *defcook, const struct La_sparc64_regs *inregs, - struct La_sparc64_retval *outregs, const char *symname) -{ - print_exit (refcook, defcook, symname, outregs->lrv_reg[0]); - - return 0; -} -#elif !defined HAVE_ARCH_PLTEXIT -# warning "pltexit for architecture not supported" -#endif diff --git a/elf/sotruss.sh b/elf/sotruss.sh deleted file mode 100755 index c83e837e0e..0000000000 --- a/elf/sotruss.sh +++ /dev/null @@ -1,152 +0,0 @@ -#! @BASH@ -# Copyright (C) 2011-2017 Free Software Foundation, Inc. -# This file is part of the GNU C Library. - -# The GNU C Library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. - -# The GNU C Library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. - -# You should have received a copy of the GNU Lesser General Public -# License along with the GNU C Library; if not, see -# <http://www.gnu.org/licenses/>. - -# We should be able to find the translation right at the beginning. -TEXTDOMAIN=libc -TEXTDOMAINDIR=@TEXTDOMAINDIR@ - -unset SOTRUSS_FROMLIST -unset SOTRUSS_TOLIST -unset SOTRUSS_OUTNAME -unset SOTRUSS_EXIT -unset SOTRUSS_NOINDENT -SOTRUSS_WHICH=$$ -lib='@PREFIX@/$LIB/audit/sotruss-lib.so' - -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 - - -e, --exit Also show exits from the function calls - -f, --follow Trace child processes - -o, --output FILENAME Write output to FILENAME (or FILENAME.$PID in case - -f is also used) instead of standard error - - -?, --help Give this help list - --usage Give a short usage message - --version Print program version" - - echo - printf $"Mandatory arguments to long options are also mandatory for any corresponding\nshort options.\n" - echo - - printf $"For bug reporting instructions, please see:\\n%s.\\n" \ - "@REPORT_BUGS_TO@" - exit 0 -} - -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 -} - -do_ambiguous() { - printf >&2 $"%s: option is ambiguous; possibilities:" - while test $# -gt 0; do - printf >&2 " '%s'" $1 - shift - done - printf >&2 "\n" - printf >&2 $"Try \`%s --help' or \`%s --usage' for more information.\n" sotruss sotruss - exit 1 -} - -while test $# -gt 0; do - case "$1" in - --v | --ve | --ver | --vers | --versi | --versio | --version) - echo "sotruss @PKGVERSION@@VERSION@" - 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. -" "2017" - printf $"Written by %s.\n" "Ulrich Drepper" - exit 0 - ;; - -\? | --h | --he | --hel | --help) - do_help - ;; - --u | --us | --usa | --usag | --usage) - printf $"Usage: %s [-ef] [-F FROMLIST] [-o FILENAME] [-T TOLIST] [--exit] - [--follow] [--from FROMLIST] [--output FILENAME] [--to TOLIST] - [--help] [--usage] [--version] [--] - EXECUTABLE [EXECUTABLE-OPTION...]\n" sotruss - exit 0 - ;; - -F | --fr | --fro | --from) - if test $# -eq 1; then - do_missing_arg "$1" - fi - shift - SOTRUSS_FROMLIST="$1" - ;; - -T | --t | --to) - if test $# -eq 1; then - do_missing_arg "$1" - fi - shift - SOTRUSS_TOLIST="$1" - ;; - -o | --o | --ou | --out | --outp | --outpu | --output) - if test $# -eq 1; then - do_missing_arg "$1" - fi - shift - SOTRUSS_OUTNAME="$1" - ;; - -f | --fo | --fol | --foll | --follo | --follow) - unset SOTRUSS_WHICH - ;; - -l | --l | --li | --lib) - if test $# -eq 1; then - do_missing_arg "$1" - fi - shift - lib="$1" - ;; - -e | --e | --ex | --exi | --exit) - SOTRUSS_EXIT=1 - ;; - --f) - do_ambiguous '--from' '--follow' - ;; - --) - shift - break - ;; - -*) - printf >&2 $"%s: unrecognized option '%c%s'\n" sotruss '-' ${1#-} - printf >&2 $"Try \`%s --help' or \`%s --usage' for more information.\n" sotruss sotruss - exit 1 - ;; - *) - break - ;; - esac - shift -done - -export SOTRUSS_FROMLIST -export SOTRUSS_TOLIST -export SOTRUSS_OUTNAME -export SOTRUSS_WHICH -export SOTRUSS_EXIT -export LD_AUDIT="$lib" - -exec "$@" diff --git a/elf/sprof.c b/elf/sprof.c deleted file mode 100644 index 85c4975360..0000000000 --- a/elf/sprof.c +++ /dev/null @@ -1,1436 +0,0 @@ -/* Read and display shared object profiling data. - Copyright (C) 1997-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. - - 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 <argp.h> -#include <dlfcn.h> -#include <elf.h> -#include <error.h> -#include <fcntl.h> -#include <inttypes.h> -#include <libintl.h> -#include <locale.h> -#include <obstack.h> -#include <search.h> -#include <stdbool.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <stdint.h> -#include <ldsodefs.h> -#include <sys/gmon.h> -#include <sys/gmon_out.h> -#include <sys/mman.h> -#include <sys/param.h> -#include <sys/stat.h> - -/* Get libc version number. */ -#include "../version.h" - -#define PACKAGE _libc_intl_domainname - - -#include <endian.h> -#if BYTE_ORDER == BIG_ENDIAN -# define byteorder ELFDATA2MSB -# define byteorder_name "big-endian" -#elif BYTE_ORDER == LITTLE_ENDIAN -# define byteorder ELFDATA2LSB -# define byteorder_name "little-endian" -#else -# error "Unknown BYTE_ORDER " BYTE_ORDER -# define byteorder ELFDATANONE -#endif - -#ifndef PATH_MAX -# define PATH_MAX 1024 -#endif - - -extern int __profile_frequency (void); - -/* Name and version of program. */ -static void print_version (FILE *stream, struct argp_state *state); -void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version; - -#define OPT_TEST 1 - -/* Definitions of arguments for argp functions. */ -static const struct argp_option options[] = -{ - { NULL, 0, NULL, 0, N_("Output selection:") }, - { "call-pairs", 'c', NULL, 0, - N_("print list of count paths and their number of use") }, - { "flat-profile", 'p', NULL, 0, - N_("generate flat profile with counts and ticks") }, - { "graph", 'q', NULL, 0, N_("generate call graph") }, - - { "test", OPT_TEST, NULL, OPTION_HIDDEN, NULL }, - { NULL, 0, NULL, 0, NULL } -}; - -/* Short description of program. */ -static const char doc[] = N_("Read and display shared object profiling data."); -//For bug reporting instructions, please see:\n -//<http://www.gnu.org/software/libc/bugs.html>.\n"); - -/* Strings for arguments in help texts. */ -static const char args_doc[] = N_("SHOBJ [PROFDATA]"); - -/* Prototype for option handler. */ -static error_t parse_opt (int key, char *arg, struct argp_state *state); - -/* Function to print some extra text in the help message. */ -static char *more_help (int key, const char *text, void *input); - -/* Data structure to communicate with argp functions. */ -static struct argp argp = -{ - options, parse_opt, args_doc, doc, NULL, more_help -}; - - -/* Operation modes. */ -static enum -{ - NONE = 0, - FLAT_MODE = 1 << 0, - CALL_GRAPH_MODE = 1 << 1, - CALL_PAIRS = 1 << 2, - - DEFAULT_MODE = FLAT_MODE | CALL_GRAPH_MODE -} mode; - -/* Nozero for testing. */ -static int do_test; - -/* Strcuture describing calls. */ -struct here_fromstruct -{ - struct here_cg_arc_record volatile *here; - uint16_t link; -}; - -/* We define a special type to address the elements of the arc table. - This is basically the `gmon_cg_arc_record' format but it includes - the room for the tag and it uses real types. */ -struct here_cg_arc_record -{ - uintptr_t from_pc; - uintptr_t self_pc; - uint32_t count; -} __attribute__ ((packed)); - - -struct known_symbol; -struct arc_list -{ - size_t idx; - uintmax_t count; - - struct arc_list *next; -}; - -static struct obstack ob_list; - - -struct known_symbol -{ - const char *name; - uintptr_t addr; - size_t size; - bool weak; - bool hidden; - - uintmax_t ticks; - uintmax_t calls; - - struct arc_list *froms; - struct arc_list *tos; -}; - - -struct shobj -{ - const char *name; /* User-provided name. */ - - struct link_map *map; - const char *dynstrtab; /* Dynamic string table of shared object. */ - const char *soname; /* Soname of shared object. */ - - uintptr_t lowpc; - uintptr_t highpc; - unsigned long int kcountsize; - size_t expected_size; /* Expected size of profiling file. */ - size_t tossize; - size_t fromssize; - size_t fromlimit; - unsigned int hashfraction; - int s_scale; - - void *symbol_map; - size_t symbol_mapsize; - const ElfW(Sym) *symtab; - size_t symtab_size; - const char *strtab; - - struct obstack ob_str; - struct obstack ob_sym; -}; - - -struct real_gmon_hist_hdr -{ - char *low_pc; - char *high_pc; - int32_t hist_size; - int32_t prof_rate; - char dimen[15]; - char dimen_abbrev; -}; - - -struct profdata -{ - void *addr; - off_t size; - - char *hist; - struct real_gmon_hist_hdr *hist_hdr; - uint16_t *kcount; - uint32_t narcs; /* Number of arcs in toset. */ - struct here_cg_arc_record *data; - uint16_t *tos; - struct here_fromstruct *froms; -}; - -/* Search tree for symbols. */ -static void *symroot; -static struct known_symbol **sortsym; -static size_t symidx; -static uintmax_t total_ticks; - -/* Prototypes for local functions. */ -static struct shobj *load_shobj (const char *name); -static void unload_shobj (struct shobj *shobj); -static struct profdata *load_profdata (const char *name, struct shobj *shobj); -static void unload_profdata (struct profdata *profdata); -static void count_total_ticks (struct shobj *shobj, struct profdata *profdata); -static void count_calls (struct shobj *shobj, struct profdata *profdata); -static void read_symbols (struct shobj *shobj); -static void add_arcs (struct profdata *profdata); -static void generate_flat_profile (struct profdata *profdata); -static void generate_call_graph (struct profdata *profdata); -static void generate_call_pair_list (struct profdata *profdata); - - -int -main (int argc, char *argv[]) -{ - const char *shobj; - const char *profdata; - struct shobj *shobj_handle; - struct profdata *profdata_handle; - int remaining; - - setlocale (LC_ALL, ""); - - /* Initialize the message catalog. */ - textdomain (_libc_intl_domainname); - - /* Parse and process arguments. */ - argp_parse (&argp, argc, argv, 0, &remaining, NULL); - - if (argc - remaining == 0 || argc - remaining > 2) - { - /* We need exactly two non-option parameter. */ - argp_help (&argp, stdout, ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR, - program_invocation_short_name); - exit (1); - } - - /* Get parameters. */ - shobj = argv[remaining]; - if (argc - remaining == 2) - profdata = argv[remaining + 1]; - else - /* No filename for the profiling data given. We will determine it - from the soname of the shobj, later. */ - profdata = NULL; - - /* First see whether we can load the shared object. */ - shobj_handle = load_shobj (shobj); - if (shobj_handle == NULL) - exit (1); - - /* We can now determine the filename for the profiling data, if - nececessary. */ - if (profdata == NULL) - { - char *newp; - const char *soname; - size_t soname_len; - - soname = shobj_handle->soname ?: basename (shobj); - soname_len = strlen (soname); - newp = (char *) alloca (soname_len + sizeof ".profile"); - stpcpy (mempcpy (newp, soname, soname_len), ".profile"); - profdata = newp; - } - - /* Now see whether the profiling data file matches the given object. */ - profdata_handle = load_profdata (profdata, shobj_handle); - if (profdata_handle == NULL) - { - unload_shobj (shobj_handle); - - exit (1); - } - - read_symbols (shobj_handle); - - /* Count the ticks. */ - count_total_ticks (shobj_handle, profdata_handle); - - /* Count the calls. */ - count_calls (shobj_handle, profdata_handle); - - /* Add the arc information. */ - add_arcs (profdata_handle); - - /* If no mode is specified fall back to the default mode. */ - if (mode == NONE) - mode = DEFAULT_MODE; - - /* Do some work. */ - if (mode & FLAT_MODE) - generate_flat_profile (profdata_handle); - - if (mode & CALL_GRAPH_MODE) - generate_call_graph (profdata_handle); - - if (mode & CALL_PAIRS) - generate_call_pair_list (profdata_handle); - - /* Free the resources. */ - unload_shobj (shobj_handle); - unload_profdata (profdata_handle); - - return 0; -} - - -/* Handle program arguments. */ -static error_t -parse_opt (int key, char *arg, struct argp_state *state) -{ - switch (key) - { - case 'c': - mode |= CALL_PAIRS; - break; - case 'p': - mode |= FLAT_MODE; - break; - case 'q': - mode |= CALL_GRAPH_MODE; - break; - case OPT_TEST: - do_test = 1; - break; - default: - return ARGP_ERR_UNKNOWN; - } - return 0; -} - - -static char * -more_help (int key, const char *text, void *input) -{ - char *tp = NULL; - switch (key) - { - case ARGP_KEY_HELP_EXTRA: - /* We print some extra information. */ - if (asprintf (&tp, gettext ("\ -For bug reporting instructions, please see:\n\ -%s.\n"), REPORT_BUGS_TO) < 0) - return NULL; - return tp; - default: - break; - } - return (char *) text; -} - - -/* Print the version information. */ -static void -print_version (FILE *stream, struct argp_state *state) -{ - fprintf (stream, "sprof %s%s\n", PKGVERSION, VERSION); - fprintf (stream, gettext ("\ -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\ -"), - "2017"); - fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper"); -} - - -/* Note that we must not use `dlopen' etc. The shobj object must not - be loaded for use. */ -static struct shobj * -load_shobj (const char *name) -{ - struct link_map *map = NULL; - struct shobj *result; - ElfW(Addr) mapstart = ~((ElfW(Addr)) 0); - ElfW(Addr) mapend = 0; - const ElfW(Phdr) *ph; - size_t textsize; - ElfW(Ehdr) *ehdr; - int fd; - ElfW(Shdr) *shdr; - size_t pagesize = getpagesize (); - - /* Since we use dlopen() we must be prepared to work around the sometimes - strange lookup rules for the shared objects. If we have a file foo.so - in the current directory and the user specfies foo.so on the command - line (without specifying a directory) we should load the file in the - current directory even if a normal dlopen() call would read the other - file. We do this by adding a directory portion to the name. */ - if (strchr (name, '/') == NULL) - { - char *load_name = (char *) alloca (strlen (name) + 3); - stpcpy (stpcpy (load_name, "./"), name); - - map = (struct link_map *) dlopen (load_name, RTLD_LAZY | __RTLD_SPROF); - } - if (map == NULL) - { - map = (struct link_map *) dlopen (name, RTLD_LAZY | __RTLD_SPROF); - if (map == NULL) - { - error (0, errno, _("failed to load shared object `%s'"), name); - return NULL; - } - } - - /* Prepare the result. */ - result = (struct shobj *) calloc (1, sizeof (struct shobj)); - if (result == NULL) - { - error (0, errno, _("cannot create internal descriptor")); - dlclose (map); - return NULL; - } - result->name = name; - result->map = map; - - /* Compute the size of the sections which contain program code. - This must match the code in dl-profile.c (_dl_start_profile). */ - for (ph = map->l_phdr; ph < &map->l_phdr[map->l_phnum]; ++ph) - if (ph->p_type == PT_LOAD && (ph->p_flags & PF_X)) - { - ElfW(Addr) start = (ph->p_vaddr & ~(pagesize - 1)); - ElfW(Addr) end = ((ph->p_vaddr + ph->p_memsz + pagesize - 1) - & ~(pagesize - 1)); - - if (start < mapstart) - mapstart = start; - if (end > mapend) - mapend = end; - } - - result->lowpc = ROUNDDOWN ((uintptr_t) (mapstart + map->l_addr), - HISTFRACTION * sizeof (HISTCOUNTER)); - result->highpc = ROUNDUP ((uintptr_t) (mapend + map->l_addr), - HISTFRACTION * sizeof (HISTCOUNTER)); - if (do_test) - printf ("load addr: %0#*" PRIxPTR "\n" - "lower bound PC: %0#*" PRIxPTR "\n" - "upper bound PC: %0#*" PRIxPTR "\n", - __ELF_NATIVE_CLASS == 32 ? 10 : 18, map->l_addr, - __ELF_NATIVE_CLASS == 32 ? 10 : 18, result->lowpc, - __ELF_NATIVE_CLASS == 32 ? 10 : 18, result->highpc); - - textsize = result->highpc - result->lowpc; - result->kcountsize = textsize / HISTFRACTION; - result->hashfraction = HASHFRACTION; - if (do_test) - printf ("hashfraction = %d\ndivider = %Zu\n", - result->hashfraction, - result->hashfraction * sizeof (struct here_fromstruct)); - result->tossize = textsize / HASHFRACTION; - result->fromlimit = textsize * ARCDENSITY / 100; - if (result->fromlimit < MINARCS) - result->fromlimit = MINARCS; - if (result->fromlimit > MAXARCS) - result->fromlimit = MAXARCS; - result->fromssize = result->fromlimit * sizeof (struct here_fromstruct); - - result->expected_size = (sizeof (struct gmon_hdr) - + 4 + sizeof (struct gmon_hist_hdr) - + result->kcountsize - + 4 + 4 - + (result->fromssize - * sizeof (struct here_cg_arc_record))); - - if (do_test) - printf ("expected size: %Zd\n", result->expected_size); - -#define SCALE_1_TO_1 0x10000L - - if (result->kcountsize < result->highpc - result->lowpc) - { - size_t range = result->highpc - result->lowpc; - size_t quot = range / result->kcountsize; - - if (quot >= SCALE_1_TO_1) - result->s_scale = 1; - else if (quot >= SCALE_1_TO_1 / 256) - result->s_scale = SCALE_1_TO_1 / quot; - else if (range > ULONG_MAX / 256) - result->s_scale = ((SCALE_1_TO_1 * 256) - / (range / (result->kcountsize / 256))); - else - result->s_scale = ((SCALE_1_TO_1 * 256) - / ((range * 256) / result->kcountsize)); - } - else - result->s_scale = SCALE_1_TO_1; - - if (do_test) - printf ("s_scale: %d\n", result->s_scale); - - /* Determine the dynamic string table. */ - if (map->l_info[DT_STRTAB] == NULL) - result->dynstrtab = NULL; - else - result->dynstrtab = (const char *) D_PTR (map, l_info[DT_STRTAB]); - if (do_test) - printf ("string table: %p\n", result->dynstrtab); - - /* Determine the soname. */ - if (map->l_info[DT_SONAME] == NULL) - result->soname = NULL; - else - result->soname = result->dynstrtab + map->l_info[DT_SONAME]->d_un.d_val; - if (do_test && result->soname != NULL) - printf ("soname: %s\n", result->soname); - - /* Now we have to load the symbol table. - - First load the section header table. */ - ehdr = (ElfW(Ehdr) *) map->l_map_start; - - /* Make sure we are on the right party. */ - if (ehdr->e_shentsize != sizeof (ElfW(Shdr))) - abort (); - - /* And we need the shared object file descriptor again. */ - fd = open (map->l_name, O_RDONLY); - if (fd == -1) - /* Dooh, this really shouldn't happen. We know the file is available. */ - error (EXIT_FAILURE, errno, _("Reopening shared object `%s' failed"), - map->l_name); - - /* Map the section header. */ - size_t size = ehdr->e_shnum * sizeof (ElfW(Shdr)); - shdr = (ElfW(Shdr) *) alloca (size); - if (pread (fd, shdr, size, ehdr->e_shoff) != size) - error (EXIT_FAILURE, errno, _("reading of section headers failed")); - - /* Get the section header string table. */ - char *shstrtab = (char *) alloca (shdr[ehdr->e_shstrndx].sh_size); - if (pread (fd, shstrtab, shdr[ehdr->e_shstrndx].sh_size, - shdr[ehdr->e_shstrndx].sh_offset) - != shdr[ehdr->e_shstrndx].sh_size) - error (EXIT_FAILURE, errno, - _("reading of section header string table failed")); - - /* Search for the ".symtab" section. */ - ElfW(Shdr) *symtab_entry = NULL; - ElfW(Shdr) *debuglink_entry = NULL; - for (int idx = 0; idx < ehdr->e_shnum; ++idx) - if (shdr[idx].sh_type == SHT_SYMTAB - && strcmp (shstrtab + shdr[idx].sh_name, ".symtab") == 0) - { - symtab_entry = &shdr[idx]; - break; - } - else if (shdr[idx].sh_type == SHT_PROGBITS - && strcmp (shstrtab + shdr[idx].sh_name, ".gnu_debuglink") == 0) - debuglink_entry = &shdr[idx]; - - /* Get the file name of the debuginfo file if necessary. */ - int symfd = fd; - if (symtab_entry == NULL && debuglink_entry != NULL) - { - size_t size = debuglink_entry->sh_size; - char *debuginfo_fname = (char *) alloca (size + 1); - debuginfo_fname[size] = '\0'; - if (pread (fd, debuginfo_fname, size, debuglink_entry->sh_offset) - != size) - { - fprintf (stderr, _("*** Cannot read debuginfo file name: %m\n")); - goto no_debuginfo; - } - - static const char procpath[] = "/proc/self/fd/%d"; - char origprocname[sizeof (procpath) + sizeof (int) * 3]; - snprintf (origprocname, sizeof (origprocname), procpath, fd); - char *origlink = (char *) alloca (PATH_MAX); - ssize_t n = readlink (origprocname, origlink, PATH_MAX - 1); - if (n == -1) - goto no_debuginfo; - origlink[n] = '\0'; - - /* Try to find the actual file. There are three places: - 1. the same directory the DSO is in - 2. in a subdir named .debug of the directory the DSO is in - 3. in /usr/lib/debug/PATH-OF-DSO - */ - char *realname = canonicalize_file_name (origlink); - char *cp = NULL; - if (realname == NULL || (cp = strrchr (realname, '/')) == NULL) - error (EXIT_FAILURE, errno, _("cannot determine file name")); - - /* Leave the last slash in place. */ - *++cp = '\0'; - - /* First add the debuginfo file name only. */ - static const char usrlibdebug[]= "/usr/lib/debug/"; - char *workbuf = (char *) alloca (sizeof (usrlibdebug) - + (cp - realname) - + strlen (debuginfo_fname)); - strcpy (stpcpy (workbuf, realname), debuginfo_fname); - - int fd2 = open (workbuf, O_RDONLY); - if (fd2 == -1) - { - strcpy (stpcpy (stpcpy (workbuf, realname), ".debug/"), - debuginfo_fname); - fd2 = open (workbuf, O_RDONLY); - if (fd2 == -1) - { - strcpy (stpcpy (stpcpy (workbuf, usrlibdebug), realname), - debuginfo_fname); - fd2 = open (workbuf, O_RDONLY); - } - } - - if (fd2 != -1) - { - ElfW(Ehdr) ehdr2; - - /* Read the ELF header. */ - if (pread (fd2, &ehdr2, sizeof (ehdr2), 0) != sizeof (ehdr2)) - error (EXIT_FAILURE, errno, - _("reading of ELF header failed")); - - /* Map the section header. */ - size_t size = ehdr2.e_shnum * sizeof (ElfW(Shdr)); - ElfW(Shdr) *shdr2 = (ElfW(Shdr) *) alloca (size); - if (pread (fd2, shdr2, size, ehdr2.e_shoff) != size) - error (EXIT_FAILURE, errno, - _("reading of section headers failed")); - - /* Get the section header string table. */ - shstrtab = (char *) alloca (shdr2[ehdr2.e_shstrndx].sh_size); - if (pread (fd2, shstrtab, shdr2[ehdr2.e_shstrndx].sh_size, - shdr2[ehdr2.e_shstrndx].sh_offset) - != shdr2[ehdr2.e_shstrndx].sh_size) - error (EXIT_FAILURE, errno, - _("reading of section header string table failed")); - - /* Search for the ".symtab" section. */ - for (int idx = 0; idx < ehdr2.e_shnum; ++idx) - if (shdr2[idx].sh_type == SHT_SYMTAB - && strcmp (shstrtab + shdr2[idx].sh_name, ".symtab") == 0) - { - symtab_entry = &shdr2[idx]; - shdr = shdr2; - symfd = fd2; - break; - } - - if (fd2 != symfd) - close (fd2); - } - } - - no_debuginfo: - if (symtab_entry == NULL) - { - fprintf (stderr, _("\ -*** The file `%s' is stripped: no detailed analysis possible\n"), - name); - result->symtab = NULL; - result->strtab = NULL; - } - else - { - ElfW(Off) min_offset, max_offset; - ElfW(Shdr) *strtab_entry; - - strtab_entry = &shdr[symtab_entry->sh_link]; - - /* Find the minimum and maximum offsets that include both the symbol - table and the string table. */ - if (symtab_entry->sh_offset < strtab_entry->sh_offset) - { - min_offset = symtab_entry->sh_offset & ~(pagesize - 1); - max_offset = strtab_entry->sh_offset + strtab_entry->sh_size; - } - else - { - min_offset = strtab_entry->sh_offset & ~(pagesize - 1); - max_offset = symtab_entry->sh_offset + symtab_entry->sh_size; - } - - result->symbol_map = mmap (NULL, max_offset - min_offset, - PROT_READ, MAP_SHARED|MAP_FILE, symfd, - min_offset); - if (result->symbol_map == MAP_FAILED) - error (EXIT_FAILURE, errno, _("failed to load symbol data")); - - result->symtab - = (const ElfW(Sym) *) ((const char *) result->symbol_map - + (symtab_entry->sh_offset - min_offset)); - result->symtab_size = symtab_entry->sh_size; - result->strtab = ((const char *) result->symbol_map - + (strtab_entry->sh_offset - min_offset)); - result->symbol_mapsize = max_offset - min_offset; - } - - /* Free the descriptor for the shared object. */ - close (fd); - if (symfd != fd) - close (symfd); - - return result; -} - - -static void -unload_shobj (struct shobj *shobj) -{ - munmap (shobj->symbol_map, shobj->symbol_mapsize); - dlclose (shobj->map); -} - - -static struct profdata * -load_profdata (const char *name, struct shobj *shobj) -{ - struct profdata *result; - int fd; - struct stat64 st; - void *addr; - uint32_t *narcsp; - size_t fromlimit; - struct here_cg_arc_record *data; - struct here_fromstruct *froms; - uint16_t *tos; - size_t fromidx; - size_t idx; - - fd = open (name, O_RDONLY); - if (fd == -1) - { - char *ext_name; - - if (errno != ENOENT || strchr (name, '/') != NULL) - /* The file exists but we are not allowed to read it or the - file does not exist and the name includes a path - specification.. */ - return NULL; - - /* A file with the given name does not exist in the current - directory, try it in the default location where the profiling - files are created. */ - ext_name = (char *) alloca (strlen (name) + sizeof "/var/tmp/"); - stpcpy (stpcpy (ext_name, "/var/tmp/"), name); - name = ext_name; - - fd = open (ext_name, O_RDONLY); - if (fd == -1) - { - /* Even this file does not exist. */ - error (0, errno, _("cannot load profiling data")); - return NULL; - } - } - - /* We have found the file, now make sure it is the right one for the - data file. */ - if (fstat64 (fd, &st) < 0) - { - error (0, errno, _("while stat'ing profiling data file")); - close (fd); - return NULL; - } - - if ((size_t) st.st_size != shobj->expected_size) - { - error (0, 0, - _("profiling data file `%s' does not match shared object `%s'"), - name, shobj->name); - close (fd); - return NULL; - } - - /* The data file is most probably the right one for our shared - object. Map it now. */ - addr = mmap (NULL, st.st_size, PROT_READ, MAP_SHARED|MAP_FILE, fd, 0); - if (addr == MAP_FAILED) - { - error (0, errno, _("failed to mmap the profiling data file")); - close (fd); - return NULL; - } - - /* We don't need the file desriptor anymore. */ - if (close (fd) < 0) - { - error (0, errno, _("error while closing the profiling data file")); - munmap (addr, st.st_size); - return NULL; - } - - /* Prepare the result. */ - result = (struct profdata *) calloc (1, sizeof (struct profdata)); - if (result == NULL) - { - error (0, errno, _("cannot create internal descriptor")); - munmap (addr, st.st_size); - return NULL; - } - - /* Store the address and size so that we can later free the resources. */ - result->addr = addr; - result->size = st.st_size; - - /* Pointer to data after the header. */ - result->hist = (char *) ((struct gmon_hdr *) addr + 1); - result->hist_hdr = (struct real_gmon_hist_hdr *) ((char *) result->hist - + sizeof (uint32_t)); - result->kcount = (uint16_t *) ((char *) result->hist + sizeof (uint32_t) - + sizeof (struct real_gmon_hist_hdr)); - - /* Compute pointer to array of the arc information. */ - narcsp = (uint32_t *) ((char *) result->kcount + shobj->kcountsize - + sizeof (uint32_t)); - result->narcs = *narcsp; - result->data = (struct here_cg_arc_record *) ((char *) narcsp - + sizeof (uint32_t)); - - /* Create the gmon_hdr we expect or write. */ - struct real_gmon_hdr - { - char cookie[4]; - int32_t version; - char spare[3 * 4]; - } gmon_hdr; - if (sizeof (gmon_hdr) != sizeof (struct gmon_hdr) - || (offsetof (struct real_gmon_hdr, cookie) - != offsetof (struct gmon_hdr, cookie)) - || (offsetof (struct real_gmon_hdr, version) - != offsetof (struct gmon_hdr, version))) - abort (); - - memcpy (&gmon_hdr.cookie[0], GMON_MAGIC, sizeof (gmon_hdr.cookie)); - gmon_hdr.version = GMON_SHOBJ_VERSION; - memset (gmon_hdr.spare, '\0', sizeof (gmon_hdr.spare)); - - /* Create the hist_hdr we expect or write. */ - struct real_gmon_hist_hdr hist_hdr; - if (sizeof (hist_hdr) != sizeof (struct gmon_hist_hdr) - || (offsetof (struct real_gmon_hist_hdr, low_pc) - != offsetof (struct gmon_hist_hdr, low_pc)) - || (offsetof (struct real_gmon_hist_hdr, high_pc) - != offsetof (struct gmon_hist_hdr, high_pc)) - || (offsetof (struct real_gmon_hist_hdr, hist_size) - != offsetof (struct gmon_hist_hdr, hist_size)) - || (offsetof (struct real_gmon_hist_hdr, prof_rate) - != offsetof (struct gmon_hist_hdr, prof_rate)) - || (offsetof (struct real_gmon_hist_hdr, dimen) - != offsetof (struct gmon_hist_hdr, dimen)) - || (offsetof (struct real_gmon_hist_hdr, dimen_abbrev) - != offsetof (struct gmon_hist_hdr, dimen_abbrev))) - abort (); - - hist_hdr.low_pc = (char *) shobj->lowpc - shobj->map->l_addr; - hist_hdr.high_pc = (char *) shobj->highpc - shobj->map->l_addr; - if (do_test) - printf ("low_pc = %p\nhigh_pc = %p\n", hist_hdr.low_pc, hist_hdr.high_pc); - hist_hdr.hist_size = shobj->kcountsize / sizeof (HISTCOUNTER); - hist_hdr.prof_rate = __profile_frequency (); - strncpy (hist_hdr.dimen, "seconds", sizeof (hist_hdr.dimen)); - hist_hdr.dimen_abbrev = 's'; - - /* Test whether the header of the profiling data is ok. */ - if (memcmp (addr, &gmon_hdr, sizeof (struct gmon_hdr)) != 0 - || *(uint32_t *) result->hist != GMON_TAG_TIME_HIST - || memcmp (result->hist_hdr, &hist_hdr, - sizeof (struct gmon_hist_hdr)) != 0 - || narcsp[-1] != GMON_TAG_CG_ARC) - { - error (0, 0, _("`%s' is no correct profile data file for `%s'"), - name, shobj->name); - if (do_test) - { - if (memcmp (addr, &gmon_hdr, sizeof (struct gmon_hdr)) != 0) - puts ("gmon_hdr differs"); - if (*(uint32_t *) result->hist != GMON_TAG_TIME_HIST) - puts ("result->hist differs"); - if (memcmp (result->hist_hdr, &hist_hdr, - sizeof (struct gmon_hist_hdr)) != 0) - puts ("hist_hdr differs"); - if (narcsp[-1] != GMON_TAG_CG_ARC) - puts ("narcsp[-1] differs"); - } - free (result); - munmap (addr, st.st_size); - return NULL; - } - - /* We are pretty sure now that this is a correct input file. Set up - the remaining information in the result structure and return. */ - result->tos = (uint16_t *) calloc (shobj->tossize + shobj->fromssize, 1); - if (result->tos == NULL) - { - error (0, errno, _("cannot create internal descriptor")); - munmap (addr, st.st_size); - free (result); - return NULL; - } - - result->froms = (struct here_fromstruct *) ((char *) result->tos - + shobj->tossize); - fromidx = 0; - - /* Now we have to process all the arc count entries. */ - fromlimit = shobj->fromlimit; - data = result->data; - froms = result->froms; - tos = result->tos; - for (idx = 0; idx < MIN (*narcsp, fromlimit); ++idx) - { - size_t to_index; - size_t newfromidx; - to_index = (data[idx].self_pc / (shobj->hashfraction * sizeof (*tos))); - newfromidx = fromidx++; - froms[newfromidx].here = &data[idx]; - froms[newfromidx].link = tos[to_index]; - tos[to_index] = newfromidx; - } - - return result; -} - - -static void -unload_profdata (struct profdata *profdata) -{ - free (profdata->tos); - munmap (profdata->addr, profdata->size); - free (profdata); -} - - -static void -count_total_ticks (struct shobj *shobj, struct profdata *profdata) -{ - volatile uint16_t *kcount = profdata->kcount; - size_t maxkidx = shobj->kcountsize; - size_t factor = 2 * (65536 / shobj->s_scale); - size_t kidx = 0; - size_t sidx = 0; - - while (sidx < symidx) - { - uintptr_t start = sortsym[sidx]->addr; - uintptr_t end = start + sortsym[sidx]->size; - - while (kidx < maxkidx && factor * kidx < start) - ++kidx; - if (kidx == maxkidx) - break; - - while (kidx < maxkidx && factor * kidx < end) - sortsym[sidx]->ticks += kcount[kidx++]; - if (kidx == maxkidx) - break; - - total_ticks += sortsym[sidx++]->ticks; - } -} - - -static size_t -find_symbol (uintptr_t addr) -{ - size_t sidx = 0; - - while (sidx < symidx) - { - uintptr_t start = sortsym[sidx]->addr; - uintptr_t end = start + sortsym[sidx]->size; - - if (addr >= start && addr < end) - return sidx; - - if (addr < start) - break; - - ++sidx; - } - - return (size_t) -1l; -} - - -static void -count_calls (struct shobj *shobj, struct profdata *profdata) -{ - struct here_cg_arc_record *data = profdata->data; - uint32_t narcs = profdata->narcs; - uint32_t cnt; - - for (cnt = 0; cnt < narcs; ++cnt) - { - uintptr_t here = data[cnt].self_pc; - size_t symbol_idx; - - /* Find the symbol for this address. */ - symbol_idx = find_symbol (here); - if (symbol_idx != (size_t) -1l) - sortsym[symbol_idx]->calls += data[cnt].count; - } -} - - -static int -symorder (const void *o1, const void *o2) -{ - const struct known_symbol *p1 = (const struct known_symbol *) o1; - const struct known_symbol *p2 = (const struct known_symbol *) o2; - - return p1->addr - p2->addr; -} - - -static void -printsym (const void *node, VISIT value, int level) -{ - if (value == leaf || value == postorder) - sortsym[symidx++] = *(struct known_symbol **) node; -} - - -static void -read_symbols (struct shobj *shobj) -{ - int n = 0; - - /* Initialize the obstacks. */ -#define obstack_chunk_alloc malloc -#define obstack_chunk_free free - obstack_init (&shobj->ob_str); - obstack_init (&shobj->ob_sym); - obstack_init (&ob_list); - - /* Process the symbols. */ - if (shobj->symtab != NULL) - { - const ElfW(Sym) *sym = shobj->symtab; - const ElfW(Sym) *sym_end - = (const ElfW(Sym) *) ((const char *) sym + shobj->symtab_size); - for (; sym < sym_end; sym++) - if ((ELFW(ST_TYPE) (sym->st_info) == STT_FUNC - || ELFW(ST_TYPE) (sym->st_info) == STT_NOTYPE) - && sym->st_size != 0) - { - struct known_symbol **existp; - struct known_symbol *newsym - = (struct known_symbol *) obstack_alloc (&shobj->ob_sym, - sizeof (*newsym)); - if (newsym == NULL) - error (EXIT_FAILURE, errno, _("cannot allocate symbol data")); - - newsym->name = &shobj->strtab[sym->st_name]; - newsym->addr = sym->st_value; - newsym->size = sym->st_size; - newsym->weak = ELFW(ST_BIND) (sym->st_info) == STB_WEAK; - newsym->hidden = (ELFW(ST_VISIBILITY) (sym->st_other) - != STV_DEFAULT); - newsym->ticks = 0; - newsym->calls = 0; - - existp = tfind (newsym, &symroot, symorder); - if (existp == NULL) - { - /* New function. */ - tsearch (newsym, &symroot, symorder); - ++n; - } - else - { - /* The function is already defined. See whether we have - a better name here. */ - if (((*existp)->hidden && !newsym->hidden) - || ((*existp)->name[0] == '_' && newsym->name[0] != '_') - || ((*existp)->name[0] != '_' && newsym->name[0] != '_' - && ((*existp)->weak && !newsym->weak))) - *existp = newsym; - else - /* We don't need the allocated memory. */ - obstack_free (&shobj->ob_sym, newsym); - } - } - } - else - { - /* Blarg, the binary is stripped. We have to rely on the - information contained in the dynamic section of the object. */ - const ElfW(Sym) *symtab = (ElfW(Sym) *) D_PTR (shobj->map, - l_info[DT_SYMTAB]); - const char *strtab = (const char *) D_PTR (shobj->map, - l_info[DT_STRTAB]); - - /* We assume that the string table follows the symbol table, - because there is no way in ELF to know the size of the - dynamic symbol table without looking at the section headers. */ - while ((void *) symtab < (void *) strtab) - { - if ((ELFW(ST_TYPE)(symtab->st_info) == STT_FUNC - || ELFW(ST_TYPE)(symtab->st_info) == STT_NOTYPE) - && symtab->st_size != 0) - { - struct known_symbol *newsym; - struct known_symbol **existp; - - newsym = - (struct known_symbol *) obstack_alloc (&shobj->ob_sym, - sizeof (*newsym)); - if (newsym == NULL) - error (EXIT_FAILURE, errno, _("cannot allocate symbol data")); - - newsym->name = &strtab[symtab->st_name]; - newsym->addr = symtab->st_value; - newsym->size = symtab->st_size; - newsym->weak = ELFW(ST_BIND) (symtab->st_info) == STB_WEAK; - newsym->hidden = (ELFW(ST_VISIBILITY) (symtab->st_other) - != STV_DEFAULT); - newsym->ticks = 0; - newsym->froms = NULL; - newsym->tos = NULL; - - existp = tfind (newsym, &symroot, symorder); - if (existp == NULL) - { - /* New function. */ - tsearch (newsym, &symroot, symorder); - ++n; - } - else - { - /* The function is already defined. See whether we have - a better name here. */ - if (((*existp)->hidden && !newsym->hidden) - || ((*existp)->name[0] == '_' && newsym->name[0] != '_') - || ((*existp)->name[0] != '_' && newsym->name[0] != '_' - && ((*existp)->weak && !newsym->weak))) - *existp = newsym; - else - /* We don't need the allocated memory. */ - obstack_free (&shobj->ob_sym, newsym); - } - } - - ++symtab; - } - } - - sortsym = malloc (n * sizeof (struct known_symbol *)); - if (sortsym == NULL) - abort (); - - twalk (symroot, printsym); -} - - -static void -add_arcs (struct profdata *profdata) -{ - uint32_t narcs = profdata->narcs; - struct here_cg_arc_record *data = profdata->data; - uint32_t cnt; - - for (cnt = 0; cnt < narcs; ++cnt) - { - /* First add the incoming arc. */ - size_t sym_idx = find_symbol (data[cnt].self_pc); - - if (sym_idx != (size_t) -1l) - { - struct known_symbol *sym = sortsym[sym_idx]; - struct arc_list *runp = sym->froms; - - while (runp != NULL - && ((data[cnt].from_pc == 0 && runp->idx != (size_t) -1l) - || (data[cnt].from_pc != 0 - && (runp->idx == (size_t) -1l - || data[cnt].from_pc < sortsym[runp->idx]->addr - || (data[cnt].from_pc - >= (sortsym[runp->idx]->addr - + sortsym[runp->idx]->size)))))) - runp = runp->next; - - if (runp == NULL) - { - /* We need a new entry. */ - struct arc_list *newp = (struct arc_list *) - obstack_alloc (&ob_list, sizeof (struct arc_list)); - - if (data[cnt].from_pc == 0) - newp->idx = (size_t) -1l; - else - newp->idx = find_symbol (data[cnt].from_pc); - newp->count = data[cnt].count; - newp->next = sym->froms; - sym->froms = newp; - } - else - /* Increment the counter for the found entry. */ - runp->count += data[cnt].count; - } - - /* Now add it to the appropriate outgoing list. */ - sym_idx = find_symbol (data[cnt].from_pc); - if (sym_idx != (size_t) -1l) - { - struct known_symbol *sym = sortsym[sym_idx]; - struct arc_list *runp = sym->tos; - - while (runp != NULL - && (runp->idx == (size_t) -1l - || data[cnt].self_pc < sortsym[runp->idx]->addr - || data[cnt].self_pc >= (sortsym[runp->idx]->addr - + sortsym[runp->idx]->size))) - runp = runp->next; - - if (runp == NULL) - { - /* We need a new entry. */ - struct arc_list *newp = (struct arc_list *) - obstack_alloc (&ob_list, sizeof (struct arc_list)); - - newp->idx = find_symbol (data[cnt].self_pc); - newp->count = data[cnt].count; - newp->next = sym->tos; - sym->tos = newp; - } - else - /* Increment the counter for the found entry. */ - runp->count += data[cnt].count; - } - } -} - - -static int -countorder (const void *p1, const void *p2) -{ - struct known_symbol *s1 = (struct known_symbol *) p1; - struct known_symbol *s2 = (struct known_symbol *) p2; - - if (s1->ticks != s2->ticks) - return (int) (s2->ticks - s1->ticks); - - if (s1->calls != s2->calls) - return (int) (s2->calls - s1->calls); - - return strcmp (s1->name, s2->name); -} - - -static double tick_unit; -static uintmax_t cumu_ticks; - -static void -printflat (const void *node, VISIT value, int level) -{ - if (value == leaf || value == postorder) - { - struct known_symbol *s = *(struct known_symbol **) node; - - cumu_ticks += s->ticks; - - printf ("%6.2f%10.2f%9.2f%9" PRIdMAX "%9.2f %s\n", - total_ticks ? (100.0 * s->ticks) / total_ticks : 0.0, - tick_unit * cumu_ticks, - tick_unit * s->ticks, - s->calls, - s->calls ? (s->ticks * 1000000) * tick_unit / s->calls : 0, - /* FIXME: don't know about called functions. */ - s->name); - } -} - - -/* ARGUSED */ -static void -freenoop (void *p) -{ -} - - -static void -generate_flat_profile (struct profdata *profdata) -{ - size_t n; - void *data = NULL; - - tick_unit = 1.0 / profdata->hist_hdr->prof_rate; - - printf ("Flat profile:\n\n" - "Each sample counts as %g %s.\n", - tick_unit, profdata->hist_hdr->dimen); - fputs (" % cumulative self self total\n" - " time seconds seconds calls us/call us/call name\n", - stdout); - - for (n = 0; n < symidx; ++n) - if (sortsym[n]->calls != 0 || sortsym[n]->ticks != 0) - tsearch (sortsym[n], &data, countorder); - - twalk (data, printflat); - - tdestroy (data, freenoop); -} - - -static void -generate_call_graph (struct profdata *profdata) -{ - size_t cnt; - - puts ("\nindex % time self children called name\n"); - - for (cnt = 0; cnt < symidx; ++cnt) - if (sortsym[cnt]->froms != NULL || sortsym[cnt]->tos != NULL) - { - struct arc_list *runp; - size_t n; - - /* First print the from-information. */ - runp = sortsym[cnt]->froms; - while (runp != NULL) - { - printf (" %8.2f%8.2f%9" PRIdMAX "/%-9" PRIdMAX " %s", - (runp->idx != (size_t) -1l - ? sortsym[runp->idx]->ticks * tick_unit : 0.0), - 0.0, /* FIXME: what's time for the children, recursive */ - runp->count, sortsym[cnt]->calls, - (runp->idx != (size_t) -1l ? - sortsym[runp->idx]->name : "<UNKNOWN>")); - - if (runp->idx != (size_t) -1l) - printf (" [%Zd]", runp->idx); - putchar_unlocked ('\n'); - - runp = runp->next; - } - - /* Info about the function itself. */ - n = printf ("[%Zu]", cnt); - printf ("%*s%5.1f%8.2f%8.2f%9" PRIdMAX " %s [%Zd]\n", - (int) (7 - n), " ", - total_ticks ? (100.0 * sortsym[cnt]->ticks) / total_ticks : 0, - sortsym[cnt]->ticks * tick_unit, - 0.0, /* FIXME: what's time for the children, recursive */ - sortsym[cnt]->calls, - sortsym[cnt]->name, cnt); - - /* Info about the functions this function calls. */ - runp = sortsym[cnt]->tos; - while (runp != NULL) - { - printf (" %8.2f%8.2f%9" PRIdMAX "/", - (runp->idx != (size_t) -1l - ? sortsym[runp->idx]->ticks * tick_unit : 0.0), - 0.0, /* FIXME: what's time for the children, recursive */ - runp->count); - - if (runp->idx != (size_t) -1l) - printf ("%-9" PRIdMAX " %s [%Zd]\n", - sortsym[runp->idx]->calls, - sortsym[runp->idx]->name, - runp->idx); - else - fputs ("??? <UNKNOWN>\n\n", stdout); - - runp = runp->next; - } - - fputs ("-----------------------------------------------\n", stdout); - } -} - - -static void -generate_call_pair_list (struct profdata *profdata) -{ - size_t cnt; - - for (cnt = 0; cnt < symidx; ++cnt) - if (sortsym[cnt]->froms != NULL || sortsym[cnt]->tos != NULL) - { - struct arc_list *runp; - - /* First print the incoming arcs. */ - runp = sortsym[cnt]->froms; - while (runp != NULL) - { - if (runp->idx == (size_t) -1l) - printf ("\ -<UNKNOWN> %-34s %9" PRIdMAX "\n", - sortsym[cnt]->name, runp->count); - runp = runp->next; - } - - /* Next the outgoing arcs. */ - runp = sortsym[cnt]->tos; - while (runp != NULL) - { - printf ("%-34s %-34s %9" PRIdMAX "\n", - sortsym[cnt]->name, - (runp->idx != (size_t) -1l - ? sortsym[runp->idx]->name : "<UNKNOWN>"), - runp->count); - runp = runp->next; - } - } -} diff --git a/elf/static-stubs.c b/elf/static-stubs.c deleted file mode 100644 index f81d5b792b..0000000000 --- a/elf/static-stubs.c +++ /dev/null @@ -1,46 +0,0 @@ -/* Stub implementations of functions to link into statically linked - programs without needing libgcc_eh. - Copyright (C) 2012-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -/* Avoid backtrace (and so _Unwind_Backtrace) dependencies from - sysdeps/unix/sysv/linux/libc_fatal.c. */ -#include <sysdeps/posix/libc_fatal.c> - -#include <stdlib.h> -#include <unwind.h> - -/* These programs do not use thread cancellation, so _Unwind_Resume - and the personality routine are never actually called. */ - -void -_Unwind_Resume (struct _Unwind_Exception *exc __attribute__ ((unused))) -{ - abort (); -} - -_Unwind_Reason_Code -__gcc_personality_v0 (int version __attribute__ ((unused)), - _Unwind_Action actions __attribute__ ((unused)), - _Unwind_Exception_Class exception_class - __attribute__ ((unused)), - struct _Unwind_Exception *ue_header - __attribute__ ((unused)), - struct _Unwind_Context *context __attribute__ ((unused))) -{ - abort (); -} diff --git a/elf/testobj.h b/elf/testobj.h deleted file mode 100644 index 1707ae340e..0000000000 --- a/elf/testobj.h +++ /dev/null @@ -1,28 +0,0 @@ -extern int preload (int a); - -extern int foo (int); - -extern int obj1func1 (int); - -extern int obj1func2 (int); - -extern int obj2func1 (int); - -extern int obj2func2 (int); - -extern int obj3func1 (int); - -extern int obj3func2 (int); - -extern int obj4func1 (int); - -extern int obj4func2 (int); - -extern int obj5func1 (int); - -extern int obj5func2 (int); - -extern int obj6func1 (int); - -extern int obj6func2 (int); - diff --git a/elf/testobj1.c b/elf/testobj1.c deleted file mode 100644 index 5ab20efd62..0000000000 --- a/elf/testobj1.c +++ /dev/null @@ -1,25 +0,0 @@ -#include <dlfcn.h> -#include <stdlib.h> - -#include "testobj.h" - -int -obj1func1 (int a __attribute__ ((unused))) -{ - return 42; -} - -int -obj1func2 (int a) -{ - return foo (a) + 10; -} - -int -preload (int a) -{ - int (*fp) (int) = dlsym (RTLD_NEXT, "preload"); - if (fp != NULL) - return fp (a) + 10; - return 10; -} diff --git a/elf/testobj1_1.c b/elf/testobj1_1.c deleted file mode 100644 index 2541a5ad1b..0000000000 --- a/elf/testobj1_1.c +++ /dev/null @@ -1,7 +0,0 @@ -#include "testobj.h" - -int -obj1func1 (int a) -{ - return 42 + obj1func2 (a); -} diff --git a/elf/testobj2.c b/elf/testobj2.c deleted file mode 100644 index 7e4b610982..0000000000 --- a/elf/testobj2.c +++ /dev/null @@ -1,32 +0,0 @@ -#include <dlfcn.h> -#include <stdlib.h> -#include <stdio.h> - -#include "testobj.h" - -int -obj2func1 (int a __attribute__ ((unused))) -{ - return 43; -} - -int -obj2func2 (int a) -{ - return obj1func1 (a) + 10; -} - -int -preload (int a) -{ - int (*fp) (int) = dlsym (RTLD_NEXT, "preload"); - if (fp != NULL) - return fp (a) + 10; - return 10; -} - -void -p (void) -{ - puts ("hello world"); -} diff --git a/elf/testobj3.c b/elf/testobj3.c deleted file mode 100644 index c025ff631a..0000000000 --- a/elf/testobj3.c +++ /dev/null @@ -1,26 +0,0 @@ -#include <dlfcn.h> -#include <stdlib.h> - -#include "testobj.h" - - -int -obj3func1 (int a __attribute__ ((unused))) -{ - return 44; -} - -int -obj3func2 (int a) -{ - return foo (a) + 42; -} - -int -preload (int a) -{ - int (*fp) (int) = dlsym (RTLD_NEXT, "preload"); - if (fp != NULL) - return fp (a) + 10; - return 10; -} diff --git a/elf/testobj4.c b/elf/testobj4.c deleted file mode 100644 index 2729ba32be..0000000000 --- a/elf/testobj4.c +++ /dev/null @@ -1,25 +0,0 @@ -#include <dlfcn.h> -#include <stdlib.h> - -#include "testobj.h" - -int -obj4func1 (int a __attribute__ ((unused))) -{ - return 55; -} - -int -obj4func2 (int a) -{ - return foo (a) + 43; -} - -int -preload (int a) -{ - int (*fp) (int) = dlsym (RTLD_NEXT, "preload"); - if (fp != NULL) - return fp (a) + 10; - return 10; -} diff --git a/elf/testobj5.c b/elf/testobj5.c deleted file mode 100644 index 9675cad88d..0000000000 --- a/elf/testobj5.c +++ /dev/null @@ -1,26 +0,0 @@ -#include <dlfcn.h> -#include <stdlib.h> - -#include "testobj.h" - - -int -obj5func1 (int a __attribute__ ((unused))) -{ - return 66; -} - -int -obj5func2 (int a) -{ - return foo (a) + 44; -} - -int -preload (int a) -{ - int (*fp) (int) = dlsym (RTLD_NEXT, "preload"); - if (fp != NULL) - return fp (a) + 10; - return 10; -} diff --git a/elf/testobj6.c b/elf/testobj6.c deleted file mode 100644 index fcba01631d..0000000000 --- a/elf/testobj6.c +++ /dev/null @@ -1,19 +0,0 @@ -#include "testobj.h" - -int -obj6func1 (int a __attribute__ ((unused))) -{ - return 77; -} - -int -obj6func2 (int a) -{ - return foo (a) + 46; -} - -int -preload (int a) -{ - return a; -} diff --git a/elf/tls-macros.h b/elf/tls-macros.h deleted file mode 100644 index e25e33b0f0..0000000000 --- a/elf/tls-macros.h +++ /dev/null @@ -1,25 +0,0 @@ -/* Macros to support TLS testing in times of missing compiler support. */ - -#define COMMON_INT_DEF(x) \ - asm (".tls_common " #x ",4,4") -/* XXX Until we get compiler support we don't need declarations. */ -#define COMMON_INT_DECL(x) - -/* XXX This definition will probably be machine specific, too. */ -#define VAR_INT_DEF(x) \ - asm (".section .tdata\n\t" \ - ".globl " #x "\n" \ - ".balign 4\n" \ - #x ":\t.long 0\n\t" \ - ".size " #x ",4\n\t" \ - ".previous") -/* XXX Until we get compiler support we don't need declarations. */ -#define VAR_INT_DECL(x) - -#include_next <tls-macros.h> - - /* XXX Each architecture must have its own asm for now. */ -#if !defined TLS_LE || !defined TLS_IE \ - || !defined TLS_LD || !defined TLS_GD -# error "No support for this architecture so far." -#endif diff --git a/elf/tlsdeschtab.h b/elf/tlsdeschtab.h deleted file mode 100644 index 3091d8b420..0000000000 --- a/elf/tlsdeschtab.h +++ /dev/null @@ -1,164 +0,0 @@ -/* Hash table for TLS descriptors. - Copyright (C) 2005-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Alexandre Oliva <aoliva@redhat.com> - - 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 TLSDESCHTAB_H -# define TLSDESCHTAB_H 1 - -#include <atomic.h> - -# ifdef SHARED - -# include <inline-hashtab.h> - -inline static int -hash_tlsdesc (void *p) -{ - struct tlsdesc_dynamic_arg *td = p; - - /* We know all entries are for the same module, so ti_offset is the - only distinguishing entry. */ - return td->tlsinfo.ti_offset; -} - -inline static int -eq_tlsdesc (void *p, void *q) -{ - struct tlsdesc_dynamic_arg *tdp = p, *tdq = q; - - return tdp->tlsinfo.ti_offset == tdq->tlsinfo.ti_offset; -} - -inline static size_t -map_generation (struct link_map *map) -{ - size_t idx = map->l_tls_modid; - struct dtv_slotinfo_list *listp = GL(dl_tls_dtv_slotinfo_list); - - /* Find the place in the dtv slotinfo list. */ - do - { - /* Does it fit in the array of this list element? */ - if (idx < listp->len) - { - /* We should never get here for a module in static TLS, so - 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].map == map && listp->slotinfo[idx].gen) - return listp->slotinfo[idx].gen; - else - break; - } - idx -= listp->len; - listp = listp->next; - } - while (listp != NULL); - - /* If we get to this point, the module still hasn't been assigned an - entry in the dtv slotinfo data structures, and it will when we're - done with relocations. At that point, the module will get a - generation number that is one past the current generation, so - return exactly that. */ - return GL(dl_tls_generation) + 1; -} - -void * -internal_function -_dl_make_tlsdesc_dynamic (struct link_map *map, size_t ti_offset) -{ - struct hashtab *ht; - void **entry; - struct tlsdesc_dynamic_arg *td, test; - - /* FIXME: We could use a per-map lock here, but is it worth it? */ - __rtld_lock_lock_recursive (GL(dl_load_lock)); - - ht = map->l_mach.tlsdesc_table; - if (! ht) - { - ht = htab_create (); - if (! ht) - { - __rtld_lock_unlock_recursive (GL(dl_load_lock)); - return 0; - } - map->l_mach.tlsdesc_table = ht; - } - - test.tlsinfo.ti_module = map->l_tls_modid; - test.tlsinfo.ti_offset = ti_offset; - entry = htab_find_slot (ht, &test, 1, hash_tlsdesc, eq_tlsdesc); - if (! entry) - { - __rtld_lock_unlock_recursive (GL(dl_load_lock)); - return 0; - } - - if (*entry) - { - td = *entry; - __rtld_lock_unlock_recursive (GL(dl_load_lock)); - return td; - } - - *entry = td = malloc (sizeof (struct tlsdesc_dynamic_arg)); - /* This may be higher than the map's generation, but it doesn't - matter much. Worst case, we'll have one extra DTV update per - thread. */ - td->gen_count = map_generation (map); - td->tlsinfo = test.tlsinfo; - - __rtld_lock_unlock_recursive (GL(dl_load_lock)); - return td; -} - -# endif /* SHARED */ - -/* The idea of the following two functions is to stop multiple threads - from attempting to resolve the same TLS descriptor without busy - waiting. Ideally, we should be able to release the lock right - after changing td->entry, and then using say a condition variable - or a futex wake to wake up any waiting threads, but let's try to - avoid introducing such dependencies. */ - -static int -_dl_tlsdesc_resolve_early_return_p (struct tlsdesc volatile *td, void *caller) -{ - if (caller != atomic_load_relaxed (&td->entry)) - return 1; - - __rtld_lock_lock_recursive (GL(dl_load_lock)); - if (caller != atomic_load_relaxed (&td->entry)) - { - __rtld_lock_unlock_recursive (GL(dl_load_lock)); - return 1; - } - - atomic_store_relaxed (&td->entry, _dl_tlsdesc_resolve_hold); - - return 0; -} - -static void -_dl_tlsdesc_wake_up_held_fixups (void) -{ - __rtld_lock_unlock_recursive (GL(dl_load_lock)); -} - -#endif diff --git a/elf/tst-_dl_addr_inside_object.c b/elf/tst-_dl_addr_inside_object.c deleted file mode 100644 index 1604b8df63..0000000000 --- a/elf/tst-_dl_addr_inside_object.c +++ /dev/null @@ -1,222 +0,0 @@ -/* Unit test for _dl_addr_inside_object. - Copyright (C) 2016-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -#include <stdio.h> -#include <stdlib.h> -#include <link.h> -#include <elf.h> -#include <libc-symbols.h> - -extern int internal_function _dl_addr_inside_object (struct link_map *l, - const ElfW(Addr) addr); - -static int -do_test (void) -{ - int ret, err = 0; - ElfW(Addr) addr; - struct link_map map; - ElfW(Phdr) header; - map.l_phdr = &header; - map.l_phnum = 1; - map.l_addr = 0x0; - /* Segment spans 0x2000 -> 0x4000. */ - header.p_vaddr = 0x2000; - header.p_memsz = 0x2000; - header.p_type = PT_LOAD; - /* Address is above the segment e.g. > 0x4000. */ - addr = 0x5000; - ret = _dl_addr_inside_object (&map, addr); - switch (ret) - { - case 0: - printf ("PASS: Above: Address is detected as outside the segment.\n"); - break; - case 1: - printf ("FAIL: Above: Address is detected as inside the segment.\n"); - err++; - break; - default: - printf ("FAIL: Above: Invalid return value.\n"); - exit (1); - } - /* Address is inside the segment e.g. 0x2000 < addr < 0x4000. */ - addr = 0x3000; - ret = _dl_addr_inside_object (&map, addr); - switch (ret) - { - case 0: - printf ("FAIL: Inside: Address is detected as outside the segment.\n"); - err++; - break; - case 1: - printf ("PASS: Inside: Address is detected as inside the segment.\n"); - break; - default: - printf ("FAIL: Inside: Invalid return value.\n"); - exit (1); - } - /* Address is below the segment e.g. < 0x2000. */ - addr = 0x1000; - ret = _dl_addr_inside_object (&map, addr); - switch (ret) - { - case 0: - printf ("PASS: Below: Address is detected as outside the segment.\n"); - break; - case 1: - printf ("FAIL: Below: Address is detected as inside the segment.\n"); - err++; - break; - default: - printf ("FAIL: Below: Invalid return value.\n"); - exit (1); - } - /* Address is in the segment and addr == p_vaddr. */ - addr = 0x2000; - ret = _dl_addr_inside_object (&map, addr); - switch (ret) - { - case 0: - printf ("FAIL: At p_vaddr: Address is detected as outside the segment.\n"); - err++; - break; - case 1: - printf ("PASS: At p_vaddr: Address is detected as inside the segment.\n"); - break; - default: - printf ("FAIL: At p_vaddr: Invalid return value.\n"); - exit (1); - } - /* Address is in the segment and addr == p_vaddr + p_memsz - 1. */ - addr = 0x2000 + 0x2000 - 0x1; - ret = _dl_addr_inside_object (&map, addr); - switch (ret) - { - case 0: - printf ("FAIL: At p_memsz-1: Address is detected as outside the segment.\n"); - err++; - break; - case 1: - printf ("PASS: At p_memsz-1: Address is detected as inside the segment.\n"); - break; - default: - printf ("FAIL: At p_memsz-1: Invalid return value.\n"); - exit (1); - } - /* Address is outside the segment and addr == p_vaddr + p_memsz. */ - addr = 0x2000 + 0x2000; - ret = _dl_addr_inside_object (&map, addr); - switch (ret) - { - case 0: - printf ("PASS: At p_memsz: Address is detected as outside the segment.\n"); - break; - case 1: - printf ("FAIL: At p_memsz: Address is detected as inside the segment.\n"); - err++; - break; - default: - printf ("FAIL: At p_memsz: Invalid return value.\n"); - exit (1); - } - /* Address is outside the segment and p_vaddr at maximum address. */ - addr = 0x0 - 0x2; - header.p_vaddr = 0x0 - 0x1; - header.p_memsz = 0x1; - ret = _dl_addr_inside_object (&map, addr); - switch (ret) - { - case 0: - printf ("PASS: At max: Address is detected as outside the segment.\n"); - break; - case 1: - printf ("FAIL: At max: Address is detected as inside the segment.\n"); - err++; - break; - default: - printf ("FAIL: At max: Invalid return value.\n"); - exit (1); - } - /* Address is outside the segment and p_vaddr at minimum address. */ - addr = 0x1; - header.p_vaddr = 0x0; - header.p_memsz = 0x1; - ret = _dl_addr_inside_object (&map, addr); - switch (ret) - { - case 0: - printf ("PASS: At min: Address is detected as outside the segment.\n"); - break; - case 1: - printf ("FAIL: At min: Address is detected as inside the segment.\n"); - err++; - break; - default: - printf ("FAIL: At min: Invalid return value.\n"); - exit (1); - } - /* Address is always inside the segment with p_memsz at max. */ - addr = 0x0; - header.p_vaddr = 0x0; - header.p_memsz = 0x0 - 0x1; - ret = _dl_addr_inside_object (&map, addr); - switch (ret) - { - case 0: - printf ("FAIL: At maxmem: Address is detected as outside the segment.\n"); - err++; - break; - case 1: - printf ("PASS: At maxmem: Address is detected as inside the segment.\n"); - break; - default: - printf ("FAIL: At maxmem: Invalid return value.\n"); - exit (1); - } - /* Attempt to wrap addr into the segment. - Pick a load address in the middle of the address space. - Place the test address at 0x0 so it wraps to the middle again. */ - map.l_addr = 0x0 - 0x1; - map.l_addr = map.l_addr / 2; - addr = 0; - /* Setup a segment covering 1/2 the address space. */ - header.p_vaddr = 0x0; - header.p_memsz = 0x0 - 0x1 - map.l_addr; - /* No matter where you place addr everything is shifted modulo l_addr - and even with this underflow you're always 1 byte away from being - in the range. */ - ret = _dl_addr_inside_object (&map, addr); - switch (ret) - { - case 0: - printf ("PASS: Underflow: Address is detected as outside the segment.\n"); - break; - case 1: - printf ("FAIL: Underflow: Address is detected as inside the segment.\n"); - err++; - break; - default: - printf ("FAIL: Underflow: Invalid return value.\n"); - exit (1); - } - - return err; -} - -#include <support/test-driver.c> diff --git a/elf/tst-addr1.c b/elf/tst-addr1.c deleted file mode 100644 index 68ff74aabd..0000000000 --- a/elf/tst-addr1.c +++ /dev/null @@ -1,25 +0,0 @@ -#include <dlfcn.h> -#include <stdio.h> -#include <string.h> - -static int -do_test (void) -{ - Dl_info i; - if (dladdr (&printf, &i) == 0) - { - puts ("not found"); - return 1; - } - printf ("found symbol %s in %s\n", i.dli_sname, i.dli_fname); - return i.dli_sname == NULL - || (strcmp (i.dli_sname, "printf") != 0 - /* On architectures which create PIC code by default - &printf may resolve to an address in libc.so - rather than in the binary. printf and _IO_printf - are aliased and which one comes first in the - hash table is up to the linker. */ - && strcmp (i.dli_sname, "_IO_printf") != 0); -} - -#include <support/test-driver.c> diff --git a/elf/tst-align.c b/elf/tst-align.c deleted file mode 100644 index 01b0b4ffb3..0000000000 --- a/elf/tst-align.c +++ /dev/null @@ -1,52 +0,0 @@ -/* Copyright (C) 2003-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Jakub Jelinek <jakub@redhat.com>, 2003. - - 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> -#include <stdlib.h> - -static int -do_test (void) -{ - static const char modname[] = "tst-alignmod.so"; - int result = 0; - void (*fp) (int *); - void *h; - - h = dlopen (modname, RTLD_LAZY); - if (h == NULL) - { - printf ("cannot open '%s': %s\n", modname, dlerror ()); - exit (1); - } - - fp = dlsym (h, "in_dso"); - if (fp == NULL) - { - printf ("cannot get symbol 'in_dso': %s\n", dlerror ()); - exit (1); - } - - fp (&result); - - dlclose (h); - - return result; -} - -#include <support/test-driver.c> diff --git a/elf/tst-align2.c b/elf/tst-align2.c deleted file mode 100644 index 78b66be20a..0000000000 --- a/elf/tst-align2.c +++ /dev/null @@ -1,155 +0,0 @@ -/* Copyright (C) 2005-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Jakub Jelinek <jakub@redhat.com>, 2005. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -#include <errno.h> -#include <stdbool.h> -#include <stdio.h> -#include <stdlib.h> -#include <sys/wait.h> -#include <tst-stack-align.h> -#include <unistd.h> - -static int res, fds[2], result; -static bool test_destructors; - -extern void in_dso (int *, bool *, int *); - -static void __attribute__ ((constructor)) con (void) -{ - res = TEST_STACK_ALIGN () ? -1 : 1; -} - -static void __attribute__ ((destructor)) des (void) -{ - if (!test_destructors) - return; - - char c = TEST_STACK_ALIGN () ? 'B' : 'A'; - write (fds[1], &c, 1); -} - -static int -do_test (void) -{ - if (!res) - { - puts ("binary's constructor has not been run"); - result = 1; - } - else if (res != 1) - { - puts ("binary's constructor has been run without sufficient alignment"); - result = 1; - } - - if (TEST_STACK_ALIGN ()) - { - puts ("insufficient stack alignment in do_test"); - result = 1; - } - - in_dso (&result, &test_destructors, &fds[1]); - - if (pipe (fds) < 0) - { - printf ("couldn't create pipe: %m\n"); - return 1; - } - - pid_t pid = fork (); - if (pid < 0) - { - printf ("fork failed: %m\n"); - return 1; - } - - if (!pid) - { - close (fds[0]); - test_destructors = true; - exit (0); - } - - close (fds[1]); - - unsigned char c; - ssize_t len; - int des_seen = 0, dso_des_seen = 0; - while ((len = TEMP_FAILURE_RETRY (read (fds[0], &c, 1))) > 0) - { - switch (c) - { - case 'B': - puts ("insufficient alignment in binary's destructor"); - result = 1; - /* FALLTHROUGH */ - case 'A': - des_seen++; - break; - case 'D': - puts ("insufficient alignment in DSO destructor"); - result = 1; - /* FALLTHROUGH */ - case 'C': - dso_des_seen++; - break; - default: - printf ("unexpected character %x read from pipe", c); - result = 1; - break; - } - } - - close (fds[0]); - - if (des_seen != 1) - { - printf ("binary destructor run %d times instead of once\n", des_seen); - result = 1; - } - - if (dso_des_seen != 1) - { - printf ("DSO destructor run %d times instead of once\n", dso_des_seen); - result = 1; - } - - int status; - pid_t termpid; - termpid = TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)); - if (termpid == -1) - { - printf ("waitpid failed: %m\n"); - result = 1; - } - else if (termpid != pid) - { - printf ("waitpid returned %ld != %ld\n", - (long int) termpid, (long int) pid); - result = 1; - } - else if (!WIFEXITED (status) || WEXITSTATUS (status)) - { - puts ("child hasn't exited with exit status 0"); - result = 1; - } - - return result; -} - -#include <support/test-driver.c> diff --git a/elf/tst-alignmod.c b/elf/tst-alignmod.c deleted file mode 100644 index b5e47be0bd..0000000000 --- a/elf/tst-alignmod.c +++ /dev/null @@ -1,52 +0,0 @@ -/* Copyright (C) 2003-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Jakub Jelinek <jakub@redhat.com>, 2003. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -#include <stdio.h> -#include <tst-stack-align.h> - -static int res, *resp; - -static void __attribute__((constructor)) -con (void) -{ - res = TEST_STACK_ALIGN () ? -1 : 1; -} - -void -in_dso (int *result) -{ - if (!res) - { - puts ("constructor has not been run"); - *result = 1; - } - else if (res != 1) - { - puts ("constructor has been run without sufficient alignment"); - *result = 1; - } - - resp = result; -} - -static void __attribute__((destructor)) -des (void) -{ - if (TEST_STACK_ALIGN ()) - *resp = 1; -} diff --git a/elf/tst-alignmod2.c b/elf/tst-alignmod2.c deleted file mode 100644 index f338ab5c27..0000000000 --- a/elf/tst-alignmod2.c +++ /dev/null @@ -1,59 +0,0 @@ -/* Copyright (C) 2003-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Jakub Jelinek <jakub@redhat.com>, 2003. - - 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 <stdbool.h> -#include <stdio.h> -#include <tst-stack-align.h> -#include <unistd.h> - -static int res, *fdp; -static bool *test_destructorsp; - -static void __attribute__((constructor)) -con (void) -{ - res = TEST_STACK_ALIGN () ? -1 : 1; -} - -void -in_dso (int *result, bool *test_destructors, int *fd) -{ - if (!res) - { - puts ("constructor has not been run"); - *result = 1; - } - else if (res != 1) - { - puts ("constructor has been run without sufficient alignment"); - *result = 1; - } - - test_destructorsp = test_destructors; - fdp = fd; -} - -static void __attribute__((destructor)) -des (void) -{ - if (!test_destructorsp || !*test_destructorsp) - return; - - char c = TEST_STACK_ALIGN () ? 'D' : 'C'; - write (*fdp, &c, 1); -} diff --git a/elf/tst-array1-static.c b/elf/tst-array1-static.c deleted file mode 100644 index 21539a4212..0000000000 --- a/elf/tst-array1-static.c +++ /dev/null @@ -1 +0,0 @@ -#include "tst-array1.c" diff --git a/elf/tst-array1.c b/elf/tst-array1.c deleted file mode 100644 index e998932b36..0000000000 --- a/elf/tst-array1.c +++ /dev/null @@ -1,103 +0,0 @@ -#include <unistd.h> - -/* Give init non-default priority so that it runs before init_array. */ -static void init (void) __attribute__ ((constructor (1000))); - -static void -init (void) -{ - write (STDOUT_FILENO, "init\n", 5); -} - -/* Give fini the same priority as init. */ -static void fini (void) __attribute__ ((destructor (1000))); - -static void -fini (void) -{ - write (STDOUT_FILENO, "fini\n", 5); -} - -static void -preinit_0 (void) -{ - write (STDOUT_FILENO, "preinit array 0\n", 16); -} - -static void -preinit_1 (void) -{ - write (STDOUT_FILENO, "preinit array 1\n", 16); -} - -static void -preinit_2 (void) -{ - write (STDOUT_FILENO, "preinit array 2\n", 16); -} - -void (*const preinit_array []) (void) - __attribute__ ((section (".preinit_array"), aligned (sizeof (void *)))) = -{ - &preinit_0, - &preinit_1, - &preinit_2 -}; - -static void -init_0 (void) -{ - write (STDOUT_FILENO, "init array 0\n", 13); -} - -static void -init_1 (void) -{ - write (STDOUT_FILENO, "init array 1\n", 13); -} - -static void -init_2 (void) -{ - write (STDOUT_FILENO, "init array 2\n", 13); -} - -void (*init_array []) (void) - __attribute__ ((section (".init_array"), aligned (sizeof (void *)))) = -{ - &init_0, - &init_1, - &init_2 -}; - -static void -fini_0 (void) -{ - write (STDOUT_FILENO, "fini array 0\n", 13); -} - -static void -fini_1 (void) -{ - write (STDOUT_FILENO, "fini array 1\n", 13); -} - -static void -fini_2 (void) -{ - write (STDOUT_FILENO, "fini array 2\n", 13); -} - -void (*fini_array []) (void) - __attribute__ ((section (".fini_array"), aligned (sizeof (void *)))) = -{ - &fini_0, - &fini_1, - &fini_2 -}; - -int -main (void) -{ - return 0; -} diff --git a/elf/tst-array1.exp b/elf/tst-array1.exp deleted file mode 100644 index cfcec9de0f..0000000000 --- a/elf/tst-array1.exp +++ /dev/null @@ -1,11 +0,0 @@ -preinit array 0 -preinit array 1 -preinit array 2 -init -init array 0 -init array 1 -init array 2 -fini array 2 -fini array 1 -fini array 0 -fini diff --git a/elf/tst-array2.c b/elf/tst-array2.c deleted file mode 100644 index 21539a4212..0000000000 --- a/elf/tst-array2.c +++ /dev/null @@ -1 +0,0 @@ -#include "tst-array1.c" diff --git a/elf/tst-array2.exp b/elf/tst-array2.exp deleted file mode 100644 index ed203525b5..0000000000 --- a/elf/tst-array2.exp +++ /dev/null @@ -1,19 +0,0 @@ -preinit array 0 -preinit array 1 -preinit array 2 -DSO init -DSO init array 0 -DSO init array 1 -DSO init array 2 -init -init array 0 -init array 1 -init array 2 -fini array 2 -fini array 1 -fini array 0 -fini -DSO fini array 2 -DSO fini array 1 -DSO fini array 0 -DSO fini diff --git a/elf/tst-array2dep.c b/elf/tst-array2dep.c deleted file mode 100644 index 2f920cdc8d..0000000000 --- a/elf/tst-array2dep.c +++ /dev/null @@ -1,71 +0,0 @@ -#include <unistd.h> - -/* Give init non-default priority so that it runs before init_array. */ -static void init (void) __attribute__ ((constructor (1000))); - -static void -init (void) -{ - write (STDOUT_FILENO, "DSO init\n", 9); -} - -/* Give fini the same priority as init. */ -static void fini (void) __attribute__ ((destructor (1000))); - -static void -fini (void) -{ - write (STDOUT_FILENO, "DSO fini\n", 9); -} - -static void -init_0 (void) -{ - write (STDOUT_FILENO, "DSO init array 0\n", 17); -} - -static void -init_1 (void) -{ - write (STDOUT_FILENO, "DSO init array 1\n", 17); -} - -static void -init_2 (void) -{ - write (STDOUT_FILENO, "DSO init array 2\n", 17); -} - -void (*init_array []) (void) - __attribute__ ((section (".init_array"), aligned (sizeof (void *)))) = -{ - &init_0, - &init_1, - &init_2 -}; - -static void -fini_0 (void) -{ - write (STDOUT_FILENO, "DSO fini array 0\n", 17); -} - -static void -fini_1 (void) -{ - write (STDOUT_FILENO, "DSO fini array 1\n", 17); -} - -static void -fini_2 (void) -{ - write (STDOUT_FILENO, "DSO fini array 2\n", 17); -} - -void (*fini_array []) (void) - __attribute__ ((section (".fini_array"), aligned (sizeof (void *)))) = -{ - &fini_0, - &fini_1, - &fini_2 -}; diff --git a/elf/tst-array3.c b/elf/tst-array3.c deleted file mode 100644 index 21539a4212..0000000000 --- a/elf/tst-array3.c +++ /dev/null @@ -1 +0,0 @@ -#include "tst-array1.c" diff --git a/elf/tst-array4.c b/elf/tst-array4.c deleted file mode 100644 index ac3d4eb716..0000000000 --- a/elf/tst-array4.c +++ /dev/null @@ -1,18 +0,0 @@ -#include <dlfcn.h> - -#define main array1_main -#include "tst-array1.c" -#undef main - -int -main (void) -{ - void *handle = dlopen ("tst-array2dep.so", RTLD_LAZY); - - array1_main (); - - if (handle != NULL) - dlclose (handle); - - return 0; -} diff --git a/elf/tst-array4.exp b/elf/tst-array4.exp deleted file mode 100644 index 560444d2e8..0000000000 --- a/elf/tst-array4.exp +++ /dev/null @@ -1,19 +0,0 @@ -preinit array 0 -preinit array 1 -preinit array 2 -init -init array 0 -init array 1 -init array 2 -DSO init -DSO init array 0 -DSO init array 1 -DSO init array 2 -DSO fini array 2 -DSO fini array 1 -DSO fini array 0 -DSO fini -fini array 2 -fini array 1 -fini array 0 -fini diff --git a/elf/tst-array5-static.c b/elf/tst-array5-static.c deleted file mode 100644 index 4ef2aba3f3..0000000000 --- a/elf/tst-array5-static.c +++ /dev/null @@ -1 +0,0 @@ -#include "tst-array5.c" diff --git a/elf/tst-array5-static.exp b/elf/tst-array5-static.exp deleted file mode 100644 index b1dc9e467b..0000000000 --- a/elf/tst-array5-static.exp +++ /dev/null @@ -1,2 +0,0 @@ -preinit array in executable: tst-array5-static -init array in executable: tst-array5-static diff --git a/elf/tst-array5.c b/elf/tst-array5.c deleted file mode 100644 index 03a5668326..0000000000 --- a/elf/tst-array5.c +++ /dev/null @@ -1,50 +0,0 @@ -#include <string.h> -#include <unistd.h> - -static void -preinit_0 (int argc __attribute__ ((unused)), char **argv) -{ - char *p = strrchr (argv [0], '/'); - - if (p == NULL) - return; - - p++; - size_t len = strlen (p); - write (STDOUT_FILENO, "preinit array in executable: ", 29); - write (STDOUT_FILENO, p, len); - write (STDOUT_FILENO, "\n", 1); -} - -void (*const preinit_array []) (int, char **) - __attribute__ ((section (".preinit_array"), aligned (sizeof (void *)))) = -{ - &preinit_0, -}; - -static void -init_0 (int argc __attribute__ ((unused)), char **argv) -{ - char *p = strrchr (argv [0], '/'); - - if (p == NULL) - return; - - p++; - size_t len = strlen (p); - write (STDOUT_FILENO, "init array in executable: ", 26); - write (STDOUT_FILENO, p, len); - write (STDOUT_FILENO, "\n", 1); -} - -void (*const init_array []) (int, char **) - __attribute__ ((section (".init_array"), aligned (sizeof (void *)))) = -{ - &init_0, -}; - -int -main (void) -{ - return 0; -} diff --git a/elf/tst-array5.exp b/elf/tst-array5.exp deleted file mode 100644 index 28b4909833..0000000000 --- a/elf/tst-array5.exp +++ /dev/null @@ -1,3 +0,0 @@ -preinit array in executable: tst-array5 -init array in DSO: tst-array5 -init array in executable: tst-array5 diff --git a/elf/tst-array5dep.c b/elf/tst-array5dep.c deleted file mode 100644 index 570d282af4..0000000000 --- a/elf/tst-array5dep.c +++ /dev/null @@ -1,23 +0,0 @@ -#include <string.h> -#include <unistd.h> - -static void -init_0 (int argc __attribute__ ((unused)), char **argv) -{ - char *p = strrchr (argv [0], '/'); - - if (p == NULL) - return; - - p++; - size_t len = strlen (p); - write (STDOUT_FILENO, "init array in DSO: ", 19); - write (STDOUT_FILENO, p, len); - write (STDOUT_FILENO, "\n", 1); -} - -void (*const init_array []) (int, char **) - __attribute__ ((section (".init_array"), aligned (sizeof (void *)))) = -{ - &init_0, -}; diff --git a/elf/tst-audit1.c b/elf/tst-audit1.c deleted file mode 100644 index 63656b4ee9..0000000000 --- a/elf/tst-audit1.c +++ /dev/null @@ -1 +0,0 @@ -#include "../io/pwd.c" diff --git a/elf/tst-audit11.c b/elf/tst-audit11.c deleted file mode 100644 index ff91a6bd6d..0000000000 --- a/elf/tst-audit11.c +++ /dev/null @@ -1,35 +0,0 @@ -/* Test version symbol binding can find a DSO replaced by la_objsearch. - Copyright (C) 2015-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -#include <dlfcn.h> -#include <stdio.h> - -int -do_test (void) -{ - puts ("Start"); - if (dlopen ("$ORIGIN/tst-audit11mod1.so", RTLD_LAZY) == NULL) - { - printf ("module not loaded: %s\n", dlerror ()); - return 1; - } - puts ("OK"); - return 0; -} - -#include <support/test-driver.c> diff --git a/elf/tst-audit11mod1.c b/elf/tst-audit11mod1.c deleted file mode 100644 index 0c0f5c6838..0000000000 --- a/elf/tst-audit11mod1.c +++ /dev/null @@ -1,24 +0,0 @@ -/* DSO directly opened by tst-audit11. - Copyright (C) 2015-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -extern int f2 (void); -int -f1 (void) -{ - return f2 (); -} diff --git a/elf/tst-audit11mod2.c b/elf/tst-audit11mod2.c deleted file mode 100644 index d5eb029744..0000000000 --- a/elf/tst-audit11mod2.c +++ /dev/null @@ -1,23 +0,0 @@ -/* DSO indirectly opened by tst-audit11, with symbol versioning. - Copyright (C) 2015-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -int -f2 (void) -{ - return 42; -} diff --git a/elf/tst-audit11mod2.map b/elf/tst-audit11mod2.map deleted file mode 100644 index 278787872c..0000000000 --- a/elf/tst-audit11mod2.map +++ /dev/null @@ -1,22 +0,0 @@ -/* Symbol versioning for the DSO indirectly opened by tst-audit11. - Copyright (C) 2015-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -V1 { - global: f2; - local: *; -}; diff --git a/elf/tst-audit12.c b/elf/tst-audit12.c deleted file mode 100644 index 62ac5f28a4..0000000000 --- a/elf/tst-audit12.c +++ /dev/null @@ -1,48 +0,0 @@ -/* Test that symbol is bound to a DSO replaced by la_objsearch. - Copyright (C) 2015-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -#include <dlfcn.h> -#include <stdio.h> - -int -do_test (void) -{ - puts ("Start"); - void *h = dlopen ("$ORIGIN/tst-audit12mod1.so", RTLD_LAZY); - if (h == NULL) - { - printf ("module not loaded: %s\n", dlerror ()); - return 1; - } - int (*fp) (void) = (int (*) (void)) dlsym (h, "f1"); - if (fp == NULL) - { - printf ("function f1 not found: %s\n", dlerror ()); - return 1; - } - int res = fp (); - if (res != 43) - { - puts ("incorrect function f2 called"); - return 1; - } - printf ("%d is OK\n", res); - return 0; -} - -#include <support/test-driver.c> diff --git a/elf/tst-audit12mod1.c b/elf/tst-audit12mod1.c deleted file mode 100644 index a48795b661..0000000000 --- a/elf/tst-audit12mod1.c +++ /dev/null @@ -1,24 +0,0 @@ -/* DSO directly opened by tst-audit12. - Copyright (C) 2015-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -extern int f2 (void); -int -f1 (void) -{ - return f2 (); -} diff --git a/elf/tst-audit12mod2.c b/elf/tst-audit12mod2.c deleted file mode 100644 index 593d02dfb6..0000000000 --- a/elf/tst-audit12mod2.c +++ /dev/null @@ -1,23 +0,0 @@ -/* Replaced DSO referenced by tst-audit12mod1.so, for tst-audit12. - Copyright (C) 2015-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -int -f2 (void) -{ - return 42; -} diff --git a/elf/tst-audit12mod2.map b/elf/tst-audit12mod2.map deleted file mode 100644 index 11e22bbdee..0000000000 --- a/elf/tst-audit12mod2.map +++ /dev/null @@ -1,22 +0,0 @@ -/* Symbol versioning for tst-audit12mod2.so used by tst-audit12. - Copyright (C) 2015-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -V1 { - global: f2; - local: *; -}; diff --git a/elf/tst-audit12mod3.c b/elf/tst-audit12mod3.c deleted file mode 100644 index 1e01bb8eea..0000000000 --- a/elf/tst-audit12mod3.c +++ /dev/null @@ -1,23 +0,0 @@ -/* Replacement DSO loaded by the audit module, for tst-audit12. - Copyright (C) 2015-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -int -f2 (void) -{ - return 43; -} diff --git a/elf/tst-audit2.c b/elf/tst-audit2.c deleted file mode 100644 index 0e66f5c328..0000000000 --- a/elf/tst-audit2.c +++ /dev/null @@ -1,60 +0,0 @@ -/* Test case for early TLS initialization in dynamic linker. */ - -#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 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 (!calloc_called) - { - /* 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; - } - - n *= m; - void *ptr = malloc (n); - if (ptr != NULL) - memset (ptr, '\0', n); - return ptr; -} - -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); - return 1; - } - - return 0; -} - -#include <support/test-driver.c> diff --git a/elf/tst-audit8.c b/elf/tst-audit8.c deleted file mode 100644 index 63656b4ee9..0000000000 --- a/elf/tst-audit8.c +++ /dev/null @@ -1 +0,0 @@ -#include "../io/pwd.c" diff --git a/elf/tst-audit9.c b/elf/tst-audit9.c deleted file mode 100644 index b9de1bf5a2..0000000000 --- a/elf/tst-audit9.c +++ /dev/null @@ -1,11 +0,0 @@ -#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; -} - -#include <support/test-driver.c> diff --git a/elf/tst-auditmod1.c b/elf/tst-auditmod1.c deleted file mode 100644 index 573e37abd6..0000000000 --- a/elf/tst-auditmod1.c +++ /dev/null @@ -1,135 +0,0 @@ -#include <dlfcn.h> -#include <link.h> -#include <stddef.h> -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <bits/wordsize.h> -#include <gnu/lib-names.h> - - -unsigned int -la_version (unsigned int v) -{ - setlinebuf (stdout); - - printf ("version: %u\n", v); - - char buf[20]; - sprintf (buf, "%u", v); - - return v; -} - -void -la_activity (uintptr_t *cookie, unsigned int flag) -{ - if (flag == LA_ACT_CONSISTENT) - printf ("activity: consistent\n"); - else if (flag == LA_ACT_ADD) - printf ("activity: add\n"); - else if (flag == LA_ACT_DELETE) - printf ("activity: delete\n"); - else - printf ("activity: unknown activity %u\n", flag); -} - -char * -la_objsearch (const char *name, uintptr_t *cookie, unsigned int flag) -{ - char buf[100]; - const char *flagstr; - if (flag == LA_SER_ORIG) - flagstr = "LA_SET_ORIG"; - else if (flag == LA_SER_LIBPATH) - flagstr = "LA_SER_LIBPATH"; - else if (flag == LA_SER_RUNPATH) - flagstr = "LA_SER_RUNPATH"; - else if (flag == LA_SER_CONFIG) - flagstr = "LA_SER_CONFIG"; - else if (flag == LA_SER_DEFAULT) - flagstr = "LA_SER_DEFAULT"; - else if (flag == LA_SER_SECURE) - flagstr = "LA_SER_SECURE"; - else - { - sprintf (buf, "unknown flag %d", flag); - flagstr = buf; - } - printf ("objsearch: %s, %s\n", name, flagstr); - - return (char *) name; -} - -unsigned int -la_objopen (struct link_map *l, Lmid_t lmid, uintptr_t *cookie) -{ - printf ("objopen: %ld, %s\n", lmid, l->l_name); - - return 3; -} - -void -la_preinit (uintptr_t *cookie) -{ - printf ("preinit\n"); -} - -unsigned int -la_objclose (uintptr_t *cookie) -{ - printf ("objclose\n"); - return 0; -} - -uintptr_t -la_symbind32 (Elf32_Sym *sym, unsigned int ndx, uintptr_t *refcook, - uintptr_t *defcook, unsigned int *flags, const char *symname) -{ - printf ("symbind32: symname=%s, st_value=%#lx, ndx=%u, flags=%u\n", - symname, (long int) sym->st_value, ndx, *flags); - - return sym->st_value; -} - -uintptr_t -la_symbind64 (Elf64_Sym *sym, unsigned int ndx, uintptr_t *refcook, - uintptr_t *defcook, unsigned int *flags, const char *symname) -{ - printf ("symbind64: symname=%s, st_value=%#lx, ndx=%u, flags=%u\n", - symname, (long int) sym->st_value, ndx, *flags); - - return sym->st_value; -} - -#include <tst-audit.h> -#if (!defined (pltenter) || !defined (pltexit) || !defined (La_regs) \ - || !defined (La_retval) || !defined (int_retval)) -# error "architecture specific code needed in sysdeps/CPU/tst-audit.h" -#endif - - -ElfW(Addr) -pltenter (ElfW(Sym) *sym, unsigned int ndx, uintptr_t *refcook, - uintptr_t *defcook, La_regs *regs, unsigned int *flags, - const char *symname, long int *framesizep) -{ - printf ("pltenter: symname=%s, st_value=%#lx, ndx=%u, flags=%u\n", - symname, (long int) sym->st_value, ndx, *flags); - - return sym->st_value; -} - -unsigned int -pltexit (ElfW(Sym) *sym, unsigned int ndx, uintptr_t *refcook, - uintptr_t *defcook, const La_regs *inregs, La_retval *outregs, - const char *symname) -{ - printf ("pltexit: symname=%s, st_value=%#lx, ndx=%u, retval=%tu\n", - symname, (long int) sym->st_value, ndx, - (ptrdiff_t) outregs->int_retval); - - return 0; -} diff --git a/elf/tst-auditmod11.c b/elf/tst-auditmod11.c deleted file mode 100644 index 18feb5efc4..0000000000 --- a/elf/tst-auditmod11.c +++ /dev/null @@ -1,39 +0,0 @@ -/* Audit module for tst-audit11. - Copyright (C) 2015-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -#include <link.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -unsigned int -la_version (unsigned int version) -{ - return version; -} - -char * -la_objsearch (const char *name, uintptr_t *cookie, unsigned int flag) -{ - if (strcmp (name, "tst-audit11mod2.so") == 0) - { - return (char *) "$ORIGIN/tst-audit11mod2.so"; - } - return (char *) name; -} diff --git a/elf/tst-auditmod12.c b/elf/tst-auditmod12.c deleted file mode 100644 index 039b7cd62b..0000000000 --- a/elf/tst-auditmod12.c +++ /dev/null @@ -1,43 +0,0 @@ -/* Audit module for tst-audit12. - Copyright (C) 2015-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -#include <link.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -unsigned int -la_version (unsigned int version) -{ - return version; -} - -char * -la_objsearch (const char *name, uintptr_t *cookie, unsigned int flag) -{ - const char target[] = "tst-audit12mod2.so"; - - size_t namelen = strlen (name); - if (namelen >= sizeof (target) - 1 - && strcmp (name + namelen - (sizeof (target) - 1), target) == 0) - { - return (char *) "$ORIGIN/tst-audit12mod3.so"; - } - return (char *) name; -} diff --git a/elf/tst-auditmod9a.c b/elf/tst-auditmod9a.c deleted file mode 100644 index 7213ade123..0000000000 --- a/elf/tst-auditmod9a.c +++ /dev/null @@ -1,15 +0,0 @@ -#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 deleted file mode 100644 index 8eeeb49986..0000000000 --- a/elf/tst-auditmod9b.c +++ /dev/null @@ -1,6 +0,0 @@ -__thread int a; - -int f(void) -{ - return ++a; -} diff --git a/elf/tst-auxv.c b/elf/tst-auxv.c deleted file mode 100644 index bc571c5fa7..0000000000 --- a/elf/tst-auxv.c +++ /dev/null @@ -1,70 +0,0 @@ -/* Copyright (C) 2013-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -#include <elf.h> -#include <errno.h> -#include <link.h> -#include <string.h> -#include <stdio.h> -#include <unistd.h> -#include <misc/sys/auxv.h> - -static int -do_test (int argc, char *argv[]) -{ - errno = 0; - const char *execfn = (const char *) getauxval (AT_NULL); - - if (errno != ENOENT) - { - printf ("errno is %d rather than %d (ENOENT) on failure\n", errno, - ENOENT); - return 1; - } - - if (execfn != NULL) - { - printf ("getauxval return value is nonzero on failure\n"); - return 1; - } - - errno = 0; - execfn = (const char *) getauxval (AT_EXECFN); - - if (execfn == NULL) - { - printf ("No AT_EXECFN found, AT_EXECFN test skipped\n"); - return 0; - } - - if (errno != 0) - { - printf ("errno erroneously set to %d on success\n", errno); - return 1; - } - - if (strcmp (argv[0], execfn) != 0) - { - printf ("Mismatch: argv[0]: %s vs. AT_EXECFN: %s\n", argv[0], execfn); - return 1; - } - - return 0; -} - -#define TEST_FUNCTION_ARGV do_test -#include <support/test-driver.c> diff --git a/elf/tst-deep1.c b/elf/tst-deep1.c deleted file mode 100644 index 97dce7ea4d..0000000000 --- a/elf/tst-deep1.c +++ /dev/null @@ -1,35 +0,0 @@ -#include <dlfcn.h> -#include <stdio.h> - -int -xyzzy (void) -{ - printf ("%s:%s\n", __FILE__, __func__); - return 21; -} - -int -back (void) -{ - printf ("%s:%s\n", __FILE__, __func__); - return 1; -} - -extern int foo (void); - -static int -do_test (void) -{ - void *p = dlopen ("$ORIGIN/tst-deep1mod2.so", RTLD_LAZY|RTLD_DEEPBIND); - - int (*f) (void) = dlsym (p, "bar"); - if (f == NULL) - { - puts (dlerror ()); - return 1; - } - - return foo () + f (); -} - -#include <support/test-driver.c> diff --git a/elf/tst-deep1mod1.c b/elf/tst-deep1mod1.c deleted file mode 100644 index cc922e6ea5..0000000000 --- a/elf/tst-deep1mod1.c +++ /dev/null @@ -1,14 +0,0 @@ -#include <stdio.h> -int -foo (void) -{ - printf ("%s:%s\n", __FILE__, __func__); - return 1; -} - -int -baz (void) -{ - printf ("%s:%s\n", __FILE__, __func__); - return 20; -} diff --git a/elf/tst-deep1mod2.c b/elf/tst-deep1mod2.c deleted file mode 100644 index b99caf0328..0000000000 --- a/elf/tst-deep1mod2.c +++ /dev/null @@ -1,16 +0,0 @@ -#include <stdio.h> -extern int baz (void); -extern int xyzzy (void); -int -bar (void) -{ - printf ("%s:%s\n", __FILE__, __func__); - return baz () + xyzzy ();; -} - -int -back (void) -{ - printf ("%s:%s\n", __FILE__, __func__); - return -1; -} diff --git a/elf/tst-deep1mod3.c b/elf/tst-deep1mod3.c deleted file mode 100644 index eee7d5c97b..0000000000 --- a/elf/tst-deep1mod3.c +++ /dev/null @@ -1,17 +0,0 @@ -#include <stdio.h> - -extern int back (void); - -int -baz (void) -{ - printf ("%s:%s\n", __FILE__, __func__); - return back (); -} - -int -xyzzy (void) -{ - printf ("%s:%s\n", __FILE__, __func__); - return 0; -} diff --git a/elf/tst-dl-iter-static.c b/elf/tst-dl-iter-static.c deleted file mode 100644 index 9a2758c8ef..0000000000 --- a/elf/tst-dl-iter-static.c +++ /dev/null @@ -1,46 +0,0 @@ -/* BZ #16046 dl_iterate_phdr static executable test. - Copyright (C) 2014-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -#include <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; -} - -#include <support/test-driver.c> diff --git a/elf/tst-dlmodcount.c b/elf/tst-dlmodcount.c deleted file mode 100644 index 34c5b25d7f..0000000000 --- a/elf/tst-dlmodcount.c +++ /dev/null @@ -1,108 +0,0 @@ -/* Copyright (C) 2004-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by David Mosberger <davidm@hpl.hp.com>, 2004. - - 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> -#include <stddef.h> -#include <stdio.h> -#include <stdlib.h> - -#define SET 0 -#define ADD 1 -#define REMOVE 2 - -#define leq(l,r) (((r) - (l)) <= ~0ULL / 2) - -static int -callback (struct dl_phdr_info *info, size_t size, void *ptr) -{ - static int last_adds = 0, last_subs = 0; - intptr_t cmd = (intptr_t) ptr; - - printf (" size = %Zu\n", size); - if (size < (offsetof (struct dl_phdr_info, dlpi_subs) - + sizeof (info->dlpi_subs))) - { - fprintf (stderr, "dl_iterate_phdr failed to pass dlpi_adds/dlpi_subs\n"); - exit (5); - } - - printf (" dlpi_adds = %Lu dlpi_subs = %Lu\n", - info->dlpi_adds, info->dlpi_subs); - - switch (cmd) - { - case SET: - break; - - case ADD: - if (leq (info->dlpi_adds, last_adds)) - { - fprintf (stderr, "dlpi_adds failed to get incremented!\n"); - exit (3); - } - break; - - case REMOVE: - if (leq (info->dlpi_subs, last_subs)) - { - fprintf (stderr, "dlpi_subs failed to get incremented!\n"); - exit (4); - } - break; - } - last_adds = info->dlpi_adds; - last_subs = info->dlpi_subs; - return -1; -} - -static void * -load (const char *path) -{ - void *handle; - - printf ("loading `%s'\n", path); - handle = dlopen (path, RTLD_LAZY); - if (!handle) - exit (1); - dl_iterate_phdr (callback, (void *)(intptr_t) ADD); - return handle; -} - -static void -unload (const char *path, void *handle) -{ - printf ("unloading `%s'\n", path); - if (dlclose (handle) < 0) - exit (2); - dl_iterate_phdr (callback, (void *)(intptr_t) REMOVE); -} - -static int -do_test (void) -{ - void *handle1, *handle2; - - dl_iterate_phdr (callback, (void *)(intptr_t) SET); - handle1 = load ("firstobj.so"); - handle2 = load ("globalmod1.so"); - unload ("firstobj.so", handle1); - unload ("globalmod1.so", handle2); - return 0; -} - -#include <support/test-driver.c> diff --git a/elf/tst-dlmopen1.c b/elf/tst-dlmopen1.c deleted file mode 100644 index 24145cfca6..0000000000 --- a/elf/tst-dlmopen1.c +++ /dev/null @@ -1,80 +0,0 @@ -#include <dlfcn.h> -#include <stdio.h> -#include <gnu/lib-names.h> - -#define TEST_SO "$ORIGIN/tst-dlmopen1mod.so" - -static int -do_test (void) -{ - void *h = dlopen (LIBC_SO, RTLD_LAZY|RTLD_NOLOAD); - if (h == NULL) - { - printf ("cannot get handle for %s: %s\n", LIBC_SO, dlerror ()); - return 1; - } - - Lmid_t ns = -10; - if (dlinfo (h, RTLD_DI_LMID, &ns) != 0) - { - printf ("dlinfo for %s in %s failed: %s\n", - LIBC_SO, __func__, dlerror ()); - return 1; - } - - if (ns != LM_ID_BASE) - { - printf ("namespace for %s not LM_ID_BASE\n", LIBC_SO); - return 1; - } - - if (dlclose (h) != 0) - { - printf ("dlclose for %s in %s failed: %s\n", - LIBC_SO, __func__, dlerror ()); - return 1; - } - - h = dlmopen (LM_ID_NEWLM, TEST_SO, RTLD_LAZY); - if (h == NULL) - { - printf ("cannot get handle for %s: %s\n", - "tst-dlmopen1mod.so", dlerror ()); - return 1; - } - - ns = -10; - if (dlinfo (h, RTLD_DI_LMID, &ns) != 0) - { - printf ("dlinfo for %s in %s failed: %s\n", - "tst-dlmopen1mod.so", __func__, dlerror ()); - return 1; - } - - if (ns == LM_ID_BASE) - { - printf ("namespace for %s is LM_ID_BASE\n", TEST_SO); - return 1; - } - - int (*fct) (Lmid_t) = dlsym (h, "foo"); - if (fct == NULL) - { - printf ("could not find %s: %s\n", "foo", dlerror ()); - return 1; - } - - if (fct (ns) != 0) - return 1; - - if (dlclose (h) != 0) - { - printf ("dlclose for %s in %s failed: %s\n", - TEST_SO, __func__, dlerror ()); - return 1; - } - - return 0; -} - -#include <support/test-driver.c> diff --git a/elf/tst-dlmopen1mod.c b/elf/tst-dlmopen1mod.c deleted file mode 100644 index 142488098a..0000000000 --- a/elf/tst-dlmopen1mod.c +++ /dev/null @@ -1,59 +0,0 @@ -#include <dlfcn.h> -#include <stdio.h> -#include <gnu/lib-names.h> - - -static int cnt; - -static void -__attribute ((constructor)) -constr (void) -{ - ++cnt; -} - - -int -foo (Lmid_t ns2) -{ - void *h = dlopen (LIBC_SO, RTLD_LAZY|RTLD_NOLOAD); - if (h == NULL) - { - printf ("cannot get handle for %s: %s\n", LIBC_SO, dlerror ()); - return 1; - } - - Lmid_t ns = -10; - if (dlinfo (h, RTLD_DI_LMID, &ns) != 0) - { - printf ("dlinfo for %s in %s failed: %s\n", - LIBC_SO, __func__, dlerror ()); - return 1; - } - - if (ns != ns2) - { - printf ("namespace for %s not LM_ID_BASE\n", LIBC_SO); - return 1; - } - - if (dlclose (h) != 0) - { - printf ("dlclose for %s in %s failed: %s\n", - LIBC_SO, __func__, dlerror ()); - return 1; - } - - if (cnt == 0) - { - puts ("constructor did not run"); - return 1; - } - else if (cnt != 1) - { - puts ("constructor did not run exactly once"); - return 1; - } - - return 0; -} diff --git a/elf/tst-dlmopen2.c b/elf/tst-dlmopen2.c deleted file mode 100644 index 8489ffba08..0000000000 --- a/elf/tst-dlmopen2.c +++ /dev/null @@ -1,69 +0,0 @@ -#include <dlfcn.h> -#include <stdio.h> -#include <string.h> -#include <gnu/lib-names.h> -#include <ldsodefs.h> - - -static int -do_test (void) -{ - int result = 0; - - for (int i = 1; i <= 10; ++i) - { - void *h[DL_NNS - 1]; - char used[DL_NNS]; - - printf ("round %d\n", i); - - memset (used, '\0', sizeof (used)); - used[LM_ID_BASE] = 1; - - for (int j = 0; j < DL_NNS - 1; ++j) - { - h[j] = dlmopen (LM_ID_NEWLM, "$ORIGIN/tst-dlmopen1mod.so", - RTLD_LAZY); - if (h[j] == NULL) - { - printf ("round %d, namespace %d: load failed: %s\n", - i, j, dlerror ()); - return 1; - } - Lmid_t ns; - if (dlinfo (h[j], RTLD_DI_LMID, &ns) != 0) - { - printf ("round %d, namespace %d: dlinfo failed: %s\n", - i, j, dlerror ()); - return 1; - } - if (ns < 0 || ns >= DL_NNS) - { - printf ("round %d, namespace %d: invalid namespace %ld", - i, j, (long int) ns); - result = 1; - } - else if (used[ns] != 0) - { - printf ("\ -round %d, namespace %d: duplicate allocate of namespace %ld", - i, j, (long int) ns); - result = 1; - } - else - used[ns] = 1; - } - - for (int j = 0; j < DL_NNS - 1; ++j) - if (dlclose (h[j]) != 0) - { - printf ("round %d, namespace %d: close failed: %s\n", - i, j, dlerror ()); - return 1; - } - } - - return result; -} - -#include <support/test-driver.c> diff --git a/elf/tst-dlmopen3.c b/elf/tst-dlmopen3.c deleted file mode 100644 index 8167507784..0000000000 --- a/elf/tst-dlmopen3.c +++ /dev/null @@ -1,21 +0,0 @@ -#include <dlfcn.h> -#include <stdio.h> - - -static int -do_test (void) -{ - void *h = dlmopen (LM_ID_NEWLM, "$ORIGIN/tst-dlmopen1mod.so", RTLD_LAZY); - if (h == NULL) - { - printf ("cannot get handle for %s: %s\n", - "tst-dlmopen1mod.so", dlerror ()); - return 1; - } - - /* Do not unload. */ - - return 0; -} - -#include <support/test-driver.c> diff --git a/elf/tst-dlopen-aout.c b/elf/tst-dlopen-aout.c deleted file mode 100644 index cccc508966..0000000000 --- a/elf/tst-dlopen-aout.c +++ /dev/null @@ -1,67 +0,0 @@ -/* 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-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. - - 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_ARGV do_test -#include <support/test-driver.c> diff --git a/elf/tst-dlopenrpath.c b/elf/tst-dlopenrpath.c deleted file mode 100644 index 77346d36f9..0000000000 --- a/elf/tst-dlopenrpath.c +++ /dev/null @@ -1,70 +0,0 @@ -/* Copyright (C) 2004-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Ulrich Drepper <drepper@redhat.com>, 2004. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -#include <dlfcn.h> -#include <errno.h> -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <sys/stat.h> - - -extern int foo (void); - -static const char testsubdir[] = PFX "test-subdir"; - - -static int -do_test (void) -{ - struct stat64 st; - int result = 1; - - if (mkdir (testsubdir, 0777) != 0 - && (errno != EEXIST - || stat64 (testsubdir, &st) != 0 - || !S_ISDIR (st.st_mode))) - { - printf ("cannot create directory %s\n", testsubdir); - return 1; - } - - if (system ("cp " PFX "firstobj.so " PFX "test-subdir/in-subdir.so") != 0) - { - puts ("cannot copy DSO"); - return 1; - } - - void *p = dlopen ("in-subdir.so", RTLD_LAZY|RTLD_LOCAL); - if (p != NULL) - { - puts ("succeeded in opening in-subdir.so from do_test"); - dlclose (p); - goto out; - } - - result = foo (); - - out: - unlink (PFX "test-subdir/in-subdir.so"); - rmdir (testsubdir); - - return result; -} - -#include <support/test-driver.c> diff --git a/elf/tst-dlopenrpathmod.c b/elf/tst-dlopenrpathmod.c deleted file mode 100644 index 6d244401bf..0000000000 --- a/elf/tst-dlopenrpathmod.c +++ /dev/null @@ -1,35 +0,0 @@ -/* Copyright (C) 2004-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Ulrich Drepper <drepper@redhat.com>, 2004. - - 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 -foo (void) -{ - void *p = dlopen ("in-subdir.so", RTLD_LAZY|RTLD_LOCAL); - if (p != NULL) - { - dlclose (p); - return 0; - } - - puts ("couldn't open in-subdir.so from foo"); - return 1; -} diff --git a/elf/tst-dlsym-error.c b/elf/tst-dlsym-error.c deleted file mode 100644 index fac8f10ccf..0000000000 --- a/elf/tst-dlsym-error.c +++ /dev/null @@ -1,113 +0,0 @@ -/* Test error reporting for dlsym, dlvsym failures. - Copyright (C) 2016-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -#include <dlfcn.h> -#include <gnu/lib-names.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -/* Used to disambiguate symbol names. */ -static int counter; - -static void -test_one (void *handle, const char *name, void *(func) (void *, const char *), - const char *suffix) -{ - ++counter; - char symbol[32]; - snprintf (symbol, sizeof (symbol), "no_such_symbol_%d", counter); - char *expected_message; - if (asprintf (&expected_message, ": undefined symbol: %s%s", - symbol, suffix) < 0) - { - printf ("error: asprintf: %m\n"); - abort (); - } - - void *addr = func (handle, symbol); - if (addr != NULL) - { - printf ("error: %s: found symbol \"no_such_symbol\"\n", name); - abort (); - } - const char *message = dlerror (); - if (message == NULL) - { - printf ("error: %s: missing error message\n", name); - abort (); - } - const char *message_without_path = strchrnul (message, ':'); - if (strcmp (message_without_path, expected_message) != 0) - { - printf ("error: %s: unexpected error message: %s\n", name, message); - abort (); - } - free (expected_message); - - message = dlerror (); - if (message != NULL) - { - printf ("error: %s: unexpected error message: %s\n", name, message); - abort (); - } -} - -static void -test_handles (const char *name, void *(func) (void *, const char *), - const char *suffix) -{ - test_one (RTLD_DEFAULT, name, func, suffix); - test_one (RTLD_NEXT, name, func, suffix); - - void *handle = dlopen (LIBC_SO, RTLD_LAZY); - if (handle == NULL) - { - printf ("error: cannot dlopen %s: %s\n", LIBC_SO, dlerror ()); - abort (); - } - test_one (handle, name, func, suffix); - dlclose (handle); -} - -static void * -dlvsym_no_such_version (void *handle, const char *name) -{ - return dlvsym (handle, name, "NO_SUCH_VERSION"); -} - -static void * -dlvsym_glibc_private (void *handle, const char *name) -{ - return dlvsym (handle, name, "GLIBC_PRIVATE"); -} - -static int -do_test (void) -{ - test_handles ("dlsym", dlsym, ""); - test_handles ("dlvsym", dlvsym_no_such_version, - ", version NO_SUCH_VERSION"); - test_handles ("dlvsym", dlvsym_glibc_private, - ", version GLIBC_PRIVATE"); - - return 0; -} - - -#include <support/test-driver.c> diff --git a/elf/tst-env-setuid-tunables.c b/elf/tst-env-setuid-tunables.c deleted file mode 100644 index afcb146e6d..0000000000 --- a/elf/tst-env-setuid-tunables.c +++ /dev/null @@ -1,75 +0,0 @@ -/* Copyright (C) 2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -/* Verify that tunables correctly filter out unsafe tunables like - glibc.malloc.check and glibc.malloc.mmap_threshold but also retain - glibc.malloc.mmap_threshold in an unprivileged child. */ - -/* This is compiled as part of the testsuite but needs to see - HAVE_TUNABLES. */ -#define _LIBC 1 -#include "config.h" -#undef _LIBC - -#define test_parent test_parent_tunables -#define test_child test_child_tunables - -static int test_child_tunables (void); -static int test_parent_tunables (void); - -#include "tst-env-setuid.c" - -#define CHILD_VALSTRING_VALUE "glibc.malloc.mmap_threshold=4096" -#define PARENT_VALSTRING_VALUE \ - "glibc.malloc.check=2:glibc.malloc.mmap_threshold=4096" - -static int -test_child_tunables (void) -{ - const char *val = getenv ("GLIBC_TUNABLES"); - -#if HAVE_TUNABLES - if (val != NULL && strcmp (val, CHILD_VALSTRING_VALUE) == 0) - return 0; - - if (val != NULL) - printf ("Unexpected GLIBC_TUNABLES VALUE %s\n", val); - - return 1; -#else - if (val != NULL) - { - printf ("GLIBC_TUNABLES not cleared\n"); - return 1; - } - return 0; -#endif -} - -static int -test_parent_tunables (void) -{ - const char *val = getenv ("GLIBC_TUNABLES"); - - if (val != NULL && strcmp (val, PARENT_VALSTRING_VALUE) == 0) - return 0; - - if (val != NULL) - printf ("Unexpected GLIBC_TUNABLES VALUE %s\n", val); - - return 1; -} diff --git a/elf/tst-env-setuid.c b/elf/tst-env-setuid.c deleted file mode 100644 index eec408eb5d..0000000000 --- a/elf/tst-env-setuid.c +++ /dev/null @@ -1,296 +0,0 @@ -/* Copyright (C) 2012-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -/* Verify that tunables correctly filter out unsafe environment variables like - MALLOC_CHECK_ and MALLOC_MMAP_THRESHOLD_ but also retain - MALLOC_MMAP_THRESHOLD_ in an unprivileged child. */ - -#include <errno.h> -#include <fcntl.h> -#include <stdlib.h> -#include <stdint.h> -#include <stdio.h> -#include <string.h> -#include <sys/stat.h> -#include <sys/wait.h> -#include <unistd.h> - -#include <support/support.h> -#include <support/test-driver.h> - -static char SETGID_CHILD[] = "setgid-child"; -#define CHILD_STATUS 42 - -/* Return a GID which is not our current GID, but is present in the - supplementary group list. */ -static gid_t -choose_gid (void) -{ - const int count = 64; - gid_t groups[count]; - int ret = getgroups (count, groups); - if (ret < 0) - { - printf ("getgroups: %m\n"); - exit (1); - } - gid_t current = getgid (); - for (int i = 0; i < ret; ++i) - { - if (groups[i] != current) - return groups[i]; - } - return 0; -} - -/* Spawn and execute a program and verify that it returns the CHILD_STATUS. */ -static pid_t -do_execve (char **args) -{ - pid_t kid = vfork (); - - if (kid < 0) - { - printf ("vfork: %m\n"); - return -1; - } - - if (kid == 0) - { - /* Child process. */ - execve (args[0], args, environ); - _exit (-errno); - } - - if (kid < 0) - return 1; - - int status; - - if (waitpid (kid, &status, 0) < 0) - { - printf ("waitpid: %m\n"); - return 1; - } - - if (WEXITSTATUS (status) == EXIT_UNSUPPORTED) - return EXIT_UNSUPPORTED; - - if (!WIFEXITED (status) || WEXITSTATUS (status) != CHILD_STATUS) - { - printf ("Unexpected exit status %d from child process\n", - WEXITSTATUS (status)); - return 1; - } - return 0; -} - -/* Copies the executable into a restricted directory, so that we can - safely make it SGID with the TARGET group ID. Then runs the - executable. */ -static int -run_executable_sgid (gid_t target) -{ - char *dirname = xasprintf ("%s/tst-tunables-setuid.%jd", - test_dir, (intmax_t) getpid ()); - char *execname = xasprintf ("%s/bin", dirname); - int infd = -1; - int outfd = -1; - int ret = 0; - if (mkdir (dirname, 0700) < 0) - { - printf ("mkdir: %m\n"); - goto err; - } - infd = open ("/proc/self/exe", O_RDONLY); - if (infd < 0) - { - printf ("open (/proc/self/exe): %m\n"); - goto err; - } - outfd = open (execname, O_WRONLY | O_CREAT | O_EXCL, 0700); - if (outfd < 0) - { - printf ("open (%s): %m\n", execname); - goto err; - } - char buf[4096]; - for (;;) - { - ssize_t rdcount = read (infd, buf, sizeof (buf)); - if (rdcount < 0) - { - printf ("read: %m\n"); - goto err; - } - if (rdcount == 0) - break; - char *p = buf; - char *end = buf + rdcount; - while (p != end) - { - ssize_t wrcount = write (outfd, buf, end - p); - if (wrcount == 0) - errno = ENOSPC; - if (wrcount <= 0) - { - printf ("write: %m\n"); - goto err; - } - p += wrcount; - } - } - if (fchown (outfd, getuid (), target) < 0) - { - printf ("fchown (%s): %m\n", execname); - goto err; - } - if (fchmod (outfd, 02750) < 0) - { - printf ("fchmod (%s): %m\n", execname); - goto err; - } - if (close (outfd) < 0) - { - printf ("close (outfd): %m\n"); - goto err; - } - if (close (infd) < 0) - { - printf ("close (infd): %m\n"); - goto err; - } - - char *args[] = {execname, SETGID_CHILD, NULL}; - - ret = do_execve (args); - -err: - if (outfd >= 0) - close (outfd); - if (infd >= 0) - close (infd); - if (execname) - { - unlink (execname); - free (execname); - } - if (dirname) - { - rmdir (dirname); - free (dirname); - } - return ret; -} - -#ifndef test_child -static int -test_child (void) -{ - if (getenv ("MALLOC_CHECK_") != NULL) - { - printf ("MALLOC_CHECK_ is still set\n"); - return 1; - } - - if (getenv ("MALLOC_MMAP_THRESHOLD_") == NULL) - { - printf ("MALLOC_MMAP_THRESHOLD_ lost\n"); - return 1; - } - - if (getenv ("LD_HWCAP_MASK") != NULL) - { - printf ("LD_HWCAP_MASK still set\n"); - return 1; - } - - return 0; -} -#endif - -#ifndef test_parent -static int -test_parent (void) -{ - if (getenv ("MALLOC_CHECK_") == NULL) - { - printf ("MALLOC_CHECK_ lost\n"); - return 1; - } - - if (getenv ("MALLOC_MMAP_THRESHOLD_") == NULL) - { - printf ("MALLOC_MMAP_THRESHOLD_ lost\n"); - return 1; - } - - if (getenv ("LD_HWCAP_MASK") == NULL) - { - printf ("LD_HWCAP_MASK lost\n"); - return 1; - } - - return 0; -} -#endif - -static int -do_test (int argc, char **argv) -{ - /* Setgid child process. */ - if (argc == 2 && strcmp (argv[1], SETGID_CHILD) == 0) - { - if (getgid () == getegid ()) - { - /* This can happen if the file system is mounted nosuid. */ - fprintf (stderr, "SGID failed: GID and EGID match (%jd)\n", - (intmax_t) getgid ()); - exit (EXIT_UNSUPPORTED); - } - - int ret = test_child (); - - if (ret != 0) - exit (1); - - exit (CHILD_STATUS); - } - else - { - if (test_parent () != 0) - exit (1); - - /* Try running a setgid program. */ - gid_t target = choose_gid (); - if (target == 0) - { - fprintf (stderr, - "Could not find a suitable GID for user %jd, skipping test\n", - (intmax_t) getuid ()); - exit (0); - } - - return run_executable_sgid (target); - } - - /* Something went wrong and our argv was corrupted. */ - _exit (1); -} - -#define TEST_FUNCTION_ARGV do_test -#include <support/test-driver.c> diff --git a/elf/tst-execstack-mod.c b/elf/tst-execstack-mod.c deleted file mode 100644 index 038e6550b5..0000000000 --- a/elf/tst-execstack-mod.c +++ /dev/null @@ -1,30 +0,0 @@ -/* Test module for making nonexecutable stacks executable - on load of a DSO that requires executable stacks. */ - -#include <stdbool.h> -#include <stdio.h> -#include <stdlib.h> - -void callme (void (*callback) (void)); - -/* This is a function that makes use of executable stack by - using a local function trampoline. */ -void -tryme (void) -{ - bool ok = false; - void callback (void) { ok = true; } - - callme (&callback); - - if (ok) - printf ("DSO called ok (local %p, trampoline %p)\n", &ok, &callback); - else - abort (); -} - -void -callme (void (*callback) (void)) -{ - (*callback) (); -} diff --git a/elf/tst-execstack-needed.c b/elf/tst-execstack-needed.c deleted file mode 100644 index 8b794a3d47..0000000000 --- a/elf/tst-execstack-needed.c +++ /dev/null @@ -1,34 +0,0 @@ -/* Test program for making nonexecutable stacks executable - on DT_NEEDED load of a DSO that requires executable stacks. */ - -#include <dlfcn.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <error.h> - -extern void tryme (void); /* from tst-execstack-mod.so */ - -static void deeper (void (*f) (void)); - -static int -do_test (void) -{ - tryme (); - - /* Test that growing the stack region gets new executable pages too. */ - deeper (&tryme); - - return 0; -} - -static void -deeper (void (*f) (void)) -{ - char stack[1100 * 1024]; - memfrob (stack, sizeof stack); - (*f) (); - memfrob (stack, sizeof stack); -} - -#include <support/test-driver.c> diff --git a/elf/tst-execstack-prog.c b/elf/tst-execstack-prog.c deleted file mode 100644 index 8663153372..0000000000 --- a/elf/tst-execstack-prog.c +++ /dev/null @@ -1,33 +0,0 @@ -/* Test program for executable stacks in an executable itself. */ - -#include <dlfcn.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <error.h> - -#include "tst-execstack-mod.c" /* This defines the `tryme' test function. */ - -static void deeper (void (*f) (void)); - -static int -do_test (void) -{ - tryme (); - - /* Test that growing the stack region gets new executable pages too. */ - deeper (&tryme); - - return 0; -} - -static void -deeper (void (*f) (void)) -{ - char stack[1100 * 1024]; - memfrob (stack, sizeof stack); - (*f) (); - memfrob (stack, sizeof stack); -} - -#include <support/test-driver.c> diff --git a/elf/tst-execstack.c b/elf/tst-execstack.c deleted file mode 100644 index 114f341d76..0000000000 --- a/elf/tst-execstack.c +++ /dev/null @@ -1,236 +0,0 @@ -/* Test program for making nonexecutable stacks executable - on load of a DSO that requires executable stacks. */ - -#include <dlfcn.h> -#include <stdbool.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <error.h> -#include <stackinfo.h> - -static void -print_maps (void) -{ -#if 0 - char *cmd = NULL; - asprintf (&cmd, "cat /proc/%d/maps", getpid ()); - system (cmd); - free (cmd); -#endif -} - -static void deeper (void (*f) (void)); - -#if USE_PTHREADS -# include <pthread.h> - -static void * -tryme_thread (void *f) -{ - (*((void (*) (void)) f)) (); - - return 0; -} - -static pthread_barrier_t startup_barrier, go_barrier; -static void * -waiter_thread (void *arg) -{ - void **f = arg; - pthread_barrier_wait (&startup_barrier); - pthread_barrier_wait (&go_barrier); - - (*((void (*) (void)) *f)) (); - - return 0; -} -#endif - -static bool allow_execstack = true; - - -static int -do_test (void) -{ - /* Check whether SELinux is enabled and disallows executable stacks. */ - FILE *fp = fopen ("/selinux/enforce", "r"); - if (fp != NULL) - { - char *line = NULL; - size_t linelen = 0; - - bool enabled = false; - ssize_t n = getline (&line, &linelen, fp); - if (n > 0 && line[0] != '0') - enabled = true; - - fclose (fp); - - if (enabled) - { - fp = fopen ("/selinux/booleans/allow_execstack", "r"); - if (fp != NULL) - { - n = getline (&line, &linelen, fp); - if (n > 0 && line[0] == '0') - allow_execstack = false; - } - - fclose (fp); - } - } - - printf ("executable stacks %sallowed\n", allow_execstack ? "" : "not "); - - static void *f; /* Address of this is used in other threads. */ - -#if USE_PTHREADS - /* Create some threads while stacks are nonexecutable. */ - #define N 5 - pthread_t thr[N]; - - pthread_barrier_init (&startup_barrier, NULL, N + 1); - pthread_barrier_init (&go_barrier, NULL, N + 1); - - for (int i = 0; i < N; ++i) - { - int rc = pthread_create (&thr[i], NULL, &waiter_thread, &f); - if (rc) - error (1, rc, "pthread_create"); - } - - /* Make sure they are all there using their stacks. */ - pthread_barrier_wait (&startup_barrier); - puts ("threads waiting"); -#endif - - print_maps (); - -#if USE_PTHREADS - void *old_stack_addr, *new_stack_addr; - size_t stack_size; - pthread_t me = pthread_self (); - pthread_attr_t attr; - int ret = 0; - - ret = pthread_getattr_np (me, &attr); - if (ret) - { - printf ("before execstack: pthread_getattr_np returned error: %s\n", - strerror (ret)); - return 1; - } - - ret = pthread_attr_getstack (&attr, &old_stack_addr, &stack_size); - if (ret) - { - printf ("before execstack: pthread_attr_getstack returned error: %s\n", - strerror (ret)); - return 1; - } -# if _STACK_GROWS_DOWN - old_stack_addr += stack_size; -# else - old_stack_addr -= stack_size; -# endif -#endif - - /* Loading this module should force stacks to become executable. */ - void *h = dlopen ("tst-execstack-mod.so", RTLD_LAZY); - if (h == NULL) - { - printf ("cannot load: %s\n", dlerror ()); - return allow_execstack; - } - - f = dlsym (h, "tryme"); - if (f == NULL) - { - printf ("symbol not found: %s\n", dlerror ()); - return 1; - } - - /* Test if that really made our stack executable. - The `tryme' function should crash if not. */ - - (*((void (*) (void)) f)) (); - - print_maps (); - -#if USE_PTHREADS - ret = pthread_getattr_np (me, &attr); - if (ret) - { - printf ("after execstack: pthread_getattr_np returned error: %s\n", - strerror (ret)); - return 1; - } - - ret = pthread_attr_getstack (&attr, &new_stack_addr, &stack_size); - if (ret) - { - printf ("after execstack: pthread_attr_getstack returned error: %s\n", - strerror (ret)); - return 1; - } - -# if _STACK_GROWS_DOWN - new_stack_addr += stack_size; -# else - new_stack_addr -= stack_size; -# endif - - /* It is possible that the dlopen'd module may have been mmapped just below - the stack. The stack size is taken as MIN(stack rlimit size, end of last - vma) in pthread_getattr_np. If rlimit is set high enough, it is possible - that the size may have changed. A subsequent call to - pthread_attr_getstack returns the size and (bottom - size) as the - stacksize and stackaddr respectively. If the size changes due to the - above, then both stacksize and stackaddr can change, but the stack bottom - should remain the same, which is computed as stackaddr + stacksize. */ - if (old_stack_addr != new_stack_addr) - { - printf ("Stack end changed, old: %p, new: %p\n", - old_stack_addr, new_stack_addr); - return 1; - } - printf ("Stack address remains the same: %p\n", old_stack_addr); -#endif - - /* Test that growing the stack region gets new executable pages too. */ - deeper ((void (*) (void)) f); - - print_maps (); - -#if USE_PTHREADS - /* Test that a fresh thread now gets an executable stack. */ - { - pthread_t th; - int rc = pthread_create (&th, NULL, &tryme_thread, f); - if (rc) - error (1, rc, "pthread_create"); - } - - puts ("threads go"); - /* The existing threads' stacks should have been changed. - Let them run to test it. */ - pthread_barrier_wait (&go_barrier); - - pthread_exit ((void *) (long int) (! allow_execstack)); -#endif - - return ! allow_execstack; -} - -static void -deeper (void (*f) (void)) -{ - char stack[1100 * 1024]; - memfrob (stack, sizeof stack); - (*f) (); - memfrob (stack, sizeof stack); -} - - -#include <support/test-driver.c> diff --git a/elf/tst-global1.c b/elf/tst-global1.c deleted file mode 100644 index 5dae74eec0..0000000000 --- a/elf/tst-global1.c +++ /dev/null @@ -1,38 +0,0 @@ -#include <dlfcn.h> -#include <stdio.h> - -static int -do_test (void) -{ - void *h1 = dlopen ("$ORIGIN/testobj6.so", RTLD_GLOBAL|RTLD_LAZY); - if (h1 == NULL) - { - puts ("cannot open testobj6"); - return 1; - } - - void *h2 = dlopen ("$ORIGIN/testobj2.so", - RTLD_GLOBAL|RTLD_DEEPBIND|RTLD_LAZY); - if (h2 == NULL) - { - puts ("cannot open testobj2"); - return 1; - } - - dlclose (h1); - - void (*f) (void) = dlsym (h2, "p"); - if (f == NULL) - { - puts ("cannot find p"); - return 1; - } - - f (); - - dlclose (h2); - - return 0; -} - -#include <support/test-driver.c> diff --git a/elf/tst-gnu2-tls1.c b/elf/tst-gnu2-tls1.c deleted file mode 100644 index b33b60a301..0000000000 --- a/elf/tst-gnu2-tls1.c +++ /dev/null @@ -1,51 +0,0 @@ -/* Test local and global dynamic models for GNU2 TLS. - Copyright (C) 2016-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -#include <stdio.h> -#include <stdlib.h> - -extern int * get_gd (void); -extern void set_gd (int); -extern int test_gd (int); -extern int * get_ld (void); -extern void set_ld (int); -extern int test_ld (int); - -__thread int gd = 1; - -static int -do_test (void) -{ - int *p; - - p = get_gd (); - set_gd (3); - if (*p != 3 || !test_gd (3)) - abort (); - - p = get_ld (); - set_ld (4); - if (*p != 4 || !test_ld (4)) - abort (); - - printf ("PASS\n"); - - return 0; -} - -#include <support/test-driver.c> diff --git a/elf/tst-gnu2-tls1mod.c b/elf/tst-gnu2-tls1mod.c deleted file mode 100644 index fa76ab1222..0000000000 --- a/elf/tst-gnu2-tls1mod.c +++ /dev/null @@ -1,56 +0,0 @@ -/* DSO used by tst-gnu2-tls1. - Copyright (C) 2016-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -static __thread int ld; - -int * -get_ld (void) -{ - return &ld; -} - -void -set_ld (int i) -{ - ld = i; -} - -int -test_ld (int i) -{ - return ld == i; -} -extern __thread int gd; - -int * -get_gd (void) -{ - return &gd; -} - -void -set_gd (int i) -{ - gd = i; -} - -int -test_gd (int i) -{ - return gd == i; -} diff --git a/elf/tst-initorder.c b/elf/tst-initorder.c deleted file mode 100644 index 9638382104..0000000000 --- a/elf/tst-initorder.c +++ /dev/null @@ -1,7 +0,0 @@ -#include <stdio.h> - -int -main( int argc, char *argv[] ) -{ - printf( "main\n" ); -} diff --git a/elf/tst-initorder.exp b/elf/tst-initorder.exp deleted file mode 100644 index 8718f65765..0000000000 --- a/elf/tst-initorder.exp +++ /dev/null @@ -1,13 +0,0 @@ -start_a1 -start_a2 -start_b1 -start_b2 -start_a3 -start_a4 -main -finish_a4 -finish_a3 -finish_b2 -finish_b1 -finish_a2 -finish_a1 diff --git a/elf/tst-initorder2.c b/elf/tst-initorder2.c deleted file mode 100644 index 050f9568b8..0000000000 --- a/elf/tst-initorder2.c +++ /dev/null @@ -1,20 +0,0 @@ -#include <stdio.h> - -#ifndef NAME -int -main (void) -{ - puts ("main"); -} -#else -static void __attribute__ ((constructor)) -init (void) -{ - puts ("init: " NAME); -} -static void __attribute__ ((destructor)) -fini (void) -{ - puts ("fini: " NAME); -} -#endif diff --git a/elf/tst-initorder2.exp b/elf/tst-initorder2.exp deleted file mode 100644 index 5169489b85..0000000000 --- a/elf/tst-initorder2.exp +++ /dev/null @@ -1,9 +0,0 @@ -init: d -init: c -init: b -init: a -main -fini: a -fini: b -fini: c -fini: d diff --git a/elf/tst-initordera1.c b/elf/tst-initordera1.c deleted file mode 100644 index f161257142..0000000000 --- a/elf/tst-initordera1.c +++ /dev/null @@ -1,16 +0,0 @@ -#include <stdio.h> - -extern void start_a1( void ) __attribute__((constructor)); -extern void finish_a1( void ) __attribute__((destructor)); - -void -start_a1( void ) -{ - printf( "start_a1\n" ); -} - -void -finish_a1( void ) -{ - printf( "finish_a1\n" ); -} diff --git a/elf/tst-initordera2.c b/elf/tst-initordera2.c deleted file mode 100644 index a5a9b42ff6..0000000000 --- a/elf/tst-initordera2.c +++ /dev/null @@ -1,16 +0,0 @@ -#include <stdio.h> - -extern void start_a2( void ) __attribute__((constructor)); -extern void finish_a2( void ) __attribute__((destructor)); - -void -start_a2( void ) -{ - printf( "start_a2\n" ); -} - -void -finish_a2( void ) -{ - printf( "finish_a2\n" ); -} diff --git a/elf/tst-initordera3.c b/elf/tst-initordera3.c deleted file mode 100644 index 1c7f496e9a..0000000000 --- a/elf/tst-initordera3.c +++ /dev/null @@ -1,16 +0,0 @@ -#include <stdio.h> - -extern void start_a3( void ) __attribute__((constructor)); -extern void finish_a3( void ) __attribute__((destructor)); - -void -start_a3( void ) -{ - printf( "start_a3\n" ); -} - -void -finish_a3( void ) -{ - printf( "finish_a3\n" ); -} diff --git a/elf/tst-initordera4.c b/elf/tst-initordera4.c deleted file mode 100644 index 70b9f5e392..0000000000 --- a/elf/tst-initordera4.c +++ /dev/null @@ -1,16 +0,0 @@ -#include <stdio.h> - -extern void start_a4( void ) __attribute__((constructor)); -extern void finish_a4( void ) __attribute__((destructor)); - -void -start_a4( void ) -{ - printf( "start_a4\n" ); -} - -void -finish_a4( void ) -{ - printf( "finish_a4\n" ); -} diff --git a/elf/tst-initorderb1.c b/elf/tst-initorderb1.c deleted file mode 100644 index 993ea3fe30..0000000000 --- a/elf/tst-initorderb1.c +++ /dev/null @@ -1,16 +0,0 @@ -#include <stdio.h> - -extern void start_b1( void ) __attribute__((constructor)); -extern void finish_b1( void ) __attribute__((destructor)); - -void -start_b1( void ) -{ - printf( "start_b1\n" ); -} - -void -finish_b1( void ) -{ - printf( "finish_b1\n" ); -} diff --git a/elf/tst-initorderb2.c b/elf/tst-initorderb2.c deleted file mode 100644 index 3334dda0a9..0000000000 --- a/elf/tst-initorderb2.c +++ /dev/null @@ -1,16 +0,0 @@ -#include <stdio.h> - -extern void start_b2( void ) __attribute__((constructor)); -extern void finish_b2( void ) __attribute__((destructor)); - -void -start_b2( void ) -{ - printf( "start_b2\n" ); -} - -void -finish_b2( void ) -{ - printf( "finish_b2\n" ); -} diff --git a/elf/tst-latepthread.c b/elf/tst-latepthread.c deleted file mode 100644 index ca2f82243d..0000000000 --- a/elf/tst-latepthread.c +++ /dev/null @@ -1,104 +0,0 @@ -/* Test that loading libpthread does not break ld.so exceptions (bug 16628). - Copyright (C) 2016-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -#include <dlfcn.h> -#include <signal.h> -#include <stdio.h> -#include <string.h> -#include <sys/wait.h> -#include <unistd.h> - -static int -do_test (void) -{ - void *handle = dlopen ("tst-latepthreadmod.so", RTLD_LOCAL | RTLD_LAZY); - if (handle == NULL) - { - printf ("error: dlopen failed: %s\n", dlerror ()); - return 1; - } - void *ptr = dlsym (handle, "trigger_dynlink_failure"); - if (ptr == NULL) - { - printf ("error: dlsym failed: %s\n", dlerror ()); - return 1; - } - int (*func) (void) = ptr; - - /* Run the actual test in a subprocess, to capture the error. */ - int fds[2]; - if (pipe (fds) < 0) - { - printf ("error: pipe: %m\n"); - return 1; - } - pid_t pid = fork (); - if (pid < 0) - { - printf ("error: fork: %m\n"); - return 1; - } - else if (pid == 0) - { - if (dup2 (fds[1], STDERR_FILENO) < 0) - _exit (2); - /* Trigger an abort. */ - func (); - _exit (3); - } - /* NB: This assumes that the abort message is so short that the pipe - does not block. */ - int status; - if (waitpid (pid, &status, 0) < 0) - { - printf ("error: waitpid: %m\n"); - return 1; - } - - /* Check the printed error message. */ - if (close (fds[1]) < 0) - { - printf ("error: close: %m\n"); - return 1; - } - char buf[512]; - /* Leave room for the NUL terminator. */ - ssize_t ret = read (fds[0], buf, sizeof (buf) - 1); - if (ret < 0) - { - printf ("error: read: %m\n"); - return 1; - } - if (ret > 0 && buf[ret - 1] == '\n') - --ret; - buf[ret] = '\0'; - printf ("info: exit status: %d, message: %s\n", status, buf); - if (strstr (buf, "undefined symbol: this_function_is_not_defined") == NULL) - { - printf ("error: message does not contain expected string\n"); - return 1; - } - if (!WIFEXITED (status) || WEXITSTATUS (status) != 127) - { - printf ("error: unexpected process exit status\n"); - return 1; - } - return 0; -} - -#include <support/test-driver.c> diff --git a/elf/tst-latepthreadmod.c b/elf/tst-latepthreadmod.c deleted file mode 100644 index 35a82d388b..0000000000 --- a/elf/tst-latepthreadmod.c +++ /dev/null @@ -1,33 +0,0 @@ -/* DSO which links against libpthread and triggers a lazy binding. - Copyright (C) 2016-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -/* This file is compiled into a DSO which loads libpthread, but fails - the dynamic linker afterwards. */ - -#include <pthread.h> - -/* Link in libpthread. */ -void *pthread_create_ptr = &pthread_create; - -int this_function_is_not_defined (void); - -int -trigger_dynlink_failure (void) -{ - return this_function_is_not_defined (); -} diff --git a/elf/tst-ldconfig-X.sh b/elf/tst-ldconfig-X.sh deleted file mode 100644 index e97ca89946..0000000000 --- a/elf/tst-ldconfig-X.sh +++ /dev/null @@ -1,62 +0,0 @@ -#!/bin/sh -# Test that ldconfig -X does not remove stale symbolic links. -# Copyright (C) 2000-2017 Free Software Foundation, Inc. -# This file is part of the GNU C Library. - -# The GNU C Library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. - -# The GNU C Library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. - -# You should have received a copy of the GNU Lesser General Public -# License along with the GNU C Library; if not, see -# <http://www.gnu.org/licenses/>. - -set -ex - -common_objpfx=$1 -test_wrapper_env=$2 -run_program_env=$3 - -testroot="${common_objpfx}elf/bug19610-test-directory" -cleanup () { - rm -rf "$testroot" -} -trap cleanup 0 - -rm -rf "$testroot" -mkdir -p $testroot/lib $testroot/etc - -# Relative symbolic link target. -ln -s libdoesnotexist.so.1.1 $testroot/lib/libdoesnotexist.so.1 - -# Absolute symbolic link target. -ln -s $testroot/opt/sw/lib/libdoesnotexist2.so.1.1 $testroot/lib/ - -errors=0 -check_files () { - for name in libdoesnotexist.so.1 libdoesnotexist2.so.1.1 ; do - path="$testroot/lib/$name" - if test ! -h $path ; then - echo "error: missing file: $path" - errors=1 - fi - done -} - -check_files - -${test_wrapper_env} \ -${run_program_env} \ -${common_objpfx}elf/ldconfig -X -f /dev/null \ - -C $testroot/etc/ld.so.cache \ - $testroot/lib - -check_files - -exit $errors diff --git a/elf/tst-leaks1-static.c b/elf/tst-leaks1-static.c deleted file mode 100644 index b956d66905..0000000000 --- a/elf/tst-leaks1-static.c +++ /dev/null @@ -1 +0,0 @@ -#include "tst-leaks1.c" diff --git a/elf/tst-leaks1.c b/elf/tst-leaks1.c deleted file mode 100644 index d67e8269c4..0000000000 --- a/elf/tst-leaks1.c +++ /dev/null @@ -1,27 +0,0 @@ -#include <stdio.h> -#include <dlfcn.h> -#include <mcheck.h> -#include <stdlib.h> - -static int -do_test (void) -{ - mtrace (); - - int ret = 0; - for (int i = 0; i < 10; i++) - { - void *h = dlopen (i < 5 ? "./tst-leaks1.c" - : "$ORIGIN/tst-leaks1.o", RTLD_LAZY); - if (h != NULL) - { - puts ("dlopen unexpectedly succeeded"); - ret = 1; - dlclose (h); - } - } - - return ret; -} - -#include <support/test-driver.c> diff --git a/elf/tst-linkall-static.c b/elf/tst-linkall-static.c deleted file mode 100644 index 8f40657244..0000000000 --- a/elf/tst-linkall-static.c +++ /dev/null @@ -1,52 +0,0 @@ -/* Test static linking against multiple libraries, to find symbol conflicts. - Copyright (C) 2016-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public License as - published by the Free Software Foundation; either version 2.1 of the - License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; see the file COPYING.LIB. If - not, see <http://www.gnu.org/licenses/>. */ - -#include <math.h> -#include <pthread.h> -#include <crypt.h> -#include <resolv.h> -#include <dlfcn.h> -#include <utmp.h> -#include <aio.h> -#include <netdb.h> - -/* These references force linking the executable against central - functions in the static libraries, pulling significant parts of - each library into the link. */ -void *references[] = - { - &pow, /* libm */ - &pthread_create, /* libpthread */ -#if USE_CRYPT - &crypt, /* libcrypt */ -#endif - &res_send, /* libresolv */ - &dlopen, /* libdl */ - &login, /* libutil */ - &aio_init, /* librt */ - &getaddrinfo_a, /* libanl */ - }; - -static int -do_test (void) -{ - /* This is a link-time test. There is nothing to run here. */ - return 0; -} - -#include <support/test-driver.c> diff --git a/elf/tst-nodelete-dlclose-dso.c b/elf/tst-nodelete-dlclose-dso.c deleted file mode 100644 index 4042c78b8a..0000000000 --- a/elf/tst-nodelete-dlclose-dso.c +++ /dev/null @@ -1,90 +0,0 @@ -/* Bug 11941: Improper assert map->l_init_called in dlclose. - Copyright (C) 2016-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -/* This is the primary DSO that is loaded by the appliation. This DSO - then loads a plugin with RTLD_NODELETE. This plugin depends on this - DSO. This dependency chain means that at application shutdown the - plugin will be destructed first. Thus by the time this DSO is - destructed we will be calling dlclose on an object that has already - been destructed. It is allowed to call dlclose in this way and - should not assert. */ -#include <stdio.h> -#include <stdlib.h> -#include <dlfcn.h> - -/* Plugin to load. */ -static void *plugin_lib = NULL; -/* Plugin function. */ -static void (*plugin_func) (void); -#define LIB_PLUGIN "tst-nodelete-dlclose-plugin.so" - -/* This function is never called but the plugin references it. - We do this to avoid any future --as-needed from removing the - plugin's DT_NEEDED on this DSO (required for the test). */ -void -primary_reference (void) -{ - printf ("INFO: Called primary_reference function.\n"); -} - -void -primary (void) -{ - char *error; - - plugin_lib = dlopen (LIB_PLUGIN, RTLD_NOW | RTLD_LOCAL | RTLD_NODELETE); - if (plugin_lib == NULL) - { - printf ("ERROR: Unable to load plugin library.\n"); - exit (EXIT_FAILURE); - } - dlerror (); - - plugin_func = (void (*) (void)) dlsym (plugin_lib, "plugin_func"); - error = dlerror (); - if (error != NULL) - { - printf ("ERROR: Unable to find symbol with error \"%s\".", - error); - exit (EXIT_FAILURE); - } - - return; -} - -__attribute__ ((destructor)) -static void -primary_dtor (void) -{ - int ret; - - printf ("INFO: Calling primary destructor.\n"); - - /* The destructor runs in the test driver also, which - hasn't called primary, in that case do nothing. */ - if (plugin_lib == NULL) - return; - - ret = dlclose (plugin_lib); - if (ret != 0) - { - printf ("ERROR: Calling dlclose failed with \"%s\"\n", - dlerror ()); - exit (EXIT_FAILURE); - } -} diff --git a/elf/tst-nodelete-dlclose-plugin.c b/elf/tst-nodelete-dlclose-plugin.c deleted file mode 100644 index 00c84d0bc0..0000000000 --- a/elf/tst-nodelete-dlclose-plugin.c +++ /dev/null @@ -1,40 +0,0 @@ -/* Bug 11941: Improper assert map->l_init_called in dlclose. - Copyright (C) 2016-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -/* This DSO simulates a plugin with a dependency on the - primary DSO loaded by the appliation. */ -#include <stdio.h> - -extern void primary_reference (void); - -void -plugin_func (void) -{ - printf ("INFO: Calling plugin function.\n"); - /* Need a reference to the DSO to ensure that a potential --as-needed - doesn't remove the DT_NEEDED entry which we rely upon to ensure - destruction ordering. */ - primary_reference (); -} - -__attribute__ ((destructor)) -static void -plugin_dtor (void) -{ - printf ("INFO: Calling plugin destructor.\n"); -} diff --git a/elf/tst-nodelete-dlclose.c b/elf/tst-nodelete-dlclose.c deleted file mode 100644 index 178673e9d0..0000000000 --- a/elf/tst-nodelete-dlclose.c +++ /dev/null @@ -1,35 +0,0 @@ -/* Bug 11941: Improper assert map->l_init_called in dlclose. - Copyright (C) 2016-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -/* This simulates an application using the primary DSO which loads the - plugin DSO. */ -#include <stdio.h> -#include <stdlib.h> - -extern void primary (void); - -static int -do_test (void) -{ - printf ("INFO: Starting application.\n"); - primary (); - printf ("INFO: Exiting application.\n"); - return 0; -} - -#include <support/test-driver.c> diff --git a/elf/tst-nodelete-opened-lib.c b/elf/tst-nodelete-opened-lib.c deleted file mode 100644 index 3e1dcdfc1b..0000000000 --- a/elf/tst-nodelete-opened-lib.c +++ /dev/null @@ -1,19 +0,0 @@ -/* Verify that objects opened with RTLD_NODELETE are not unloaded - the DSO. - Copyright (C) 2015-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -int foo_var = 42; diff --git a/elf/tst-nodelete-opened.c b/elf/tst-nodelete-opened.c deleted file mode 100644 index d71efa4603..0000000000 --- a/elf/tst-nodelete-opened.c +++ /dev/null @@ -1,68 +0,0 @@ -/* Verify that an already opened DSO opened agained with RTLD_NODELETE actually - sets the NODELETE flag. - - Copyright (C) 2015-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -#include <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; -} - -#include <support/test-driver.c> diff --git a/elf/tst-nodelete-rtldmod.cc b/elf/tst-nodelete-rtldmod.cc deleted file mode 100644 index 740e1d8181..0000000000 --- a/elf/tst-nodelete-rtldmod.cc +++ /dev/null @@ -1,6 +0,0 @@ -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 deleted file mode 100644 index 632b303d58..0000000000 --- a/elf/tst-nodelete-uniquemod.cc +++ /dev/null @@ -1,14 +0,0 @@ -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 deleted file mode 100644 index 740e1d8181..0000000000 --- a/elf/tst-nodelete-zmod.cc +++ /dev/null @@ -1,6 +0,0 @@ -extern int not_exist (void); - -int foo (void) -{ - return not_exist (); -} diff --git a/elf/tst-nodelete.cc b/elf/tst-nodelete.cc deleted file mode 100644 index 5752e7df26..0000000000 --- a/elf/tst-nodelete.cc +++ /dev/null @@ -1,50 +0,0 @@ -#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; -} - -#include <support/test-driver.c> diff --git a/elf/tst-nodelete2.c b/elf/tst-nodelete2.c deleted file mode 100644 index 010c4ae237..0000000000 --- a/elf/tst-nodelete2.c +++ /dev/null @@ -1,36 +0,0 @@ -#include "../dlfcn/dlfcn.h" -#include <stdio.h> -#include <stdlib.h> -#include <gnu/lib-names.h> - -static int -do_test (void) -{ - int result = 0; - - printf ("\nOpening pthread library.\n"); - void *pthread = dlopen (LIBPTHREAD_SO, RTLD_LAZY); - - /* This is a test for correct DF_1_NODELETE clearing when dlopen failure - happens. We should clear DF_1_NODELETE for failed library only, because - doing this for others (e.g. libpthread) might cause them to be unloaded, - that may lead to some global references (e.g. __rtld_lock_unlock) to be - broken. The dlopen should fail because of undefined symbols in shared - library, that cause DF_1_NODELETE to be cleared. For libpthread, this - flag should be set, because if not, SIGSEGV will happen in dlclose. */ - if (dlopen ("tst-nodelete2mod.so", RTLD_NOW) != NULL) - { - printf ("Unique symbols test failed\n"); - result = 1; - } - - if (pthread) - dlclose (pthread); - - if (result == 0) - printf ("SUCCESS\n"); - - return result; -} - -#include <support/test-driver.c> diff --git a/elf/tst-nodelete2mod.c b/elf/tst-nodelete2mod.c deleted file mode 100644 index e88c756f5e..0000000000 --- a/elf/tst-nodelete2mod.c +++ /dev/null @@ -1,7 +0,0 @@ -/* Undefined symbol. */ -extern int not_exist (void); - -int foo (void) -{ - return not_exist (); -} diff --git a/elf/tst-noload.c b/elf/tst-noload.c deleted file mode 100644 index 3fb2895e2c..0000000000 --- a/elf/tst-noload.c +++ /dev/null @@ -1,72 +0,0 @@ -/* Verify that RTLD_NOLOAD works as expected. - - Copyright (C) 2016-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -#include <dlfcn.h> -#include <stdio.h> -#include <gnu/lib-names.h> - -static int -do_test (void) -{ - /* Test that no object is loaded with RTLD_NOLOAD. */ - void *h1 = dlopen (LIBM_SO, RTLD_LAZY | RTLD_NOLOAD); - if (h1 != NULL) - { - printf ("h1: DSO has been loaded while it should have not\n"); - return 1; - } - - /* This used to segfault in some glibc versions. */ - void *h2 = dlopen (LIBM_SO, RTLD_LAZY | RTLD_NOLOAD | RTLD_NODELETE); - if (h2 != NULL) - { - printf ("h2: DSO has been loaded while it should have not\n"); - return 1; - } - - /* Test that loading an already loaded object returns the same. */ - void *h3 = dlopen (LIBM_SO, RTLD_LAZY); - if (h3 == NULL) - { - printf ("h3: failed to open DSO: %s\n", dlerror ()); - return 1; - } - void *h4 = dlopen (LIBM_SO, RTLD_LAZY | RTLD_NOLOAD); - if (h4 == NULL) - { - printf ("h4: failed to open DSO: %s\n", dlerror ()); - return 1; - } - if (h4 != h3) - { - printf ("h4: should return the same object\n"); - return 1; - } - - /* Cleanup */ - if (dlclose (h3) != 0) - { - printf ("h3: dlclose failed: %s\n", dlerror ()); - return 1; - } - - return 0; -} - -#include <support/test-driver.c> diff --git a/elf/tst-null-argv-lib.c b/elf/tst-null-argv-lib.c deleted file mode 100644 index 12af03ba95..0000000000 --- a/elf/tst-null-argv-lib.c +++ /dev/null @@ -1,24 +0,0 @@ -/* 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-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -void -foo (void) -{ - return; -} diff --git a/elf/tst-null-argv.c b/elf/tst-null-argv.c deleted file mode 100644 index 21b87327c1..0000000000 --- a/elf/tst-null-argv.c +++ /dev/null @@ -1,36 +0,0 @@ -/* Verify that program does not crash when LD_DEBUG is set and the program name - is not available. - Copyright (C) 2013-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -extern void foo (void); - -int -do_test (int argc, char **argv) -{ - argv[0] = argv[1]; - argc--; - - /* This should result in a symbol lookup, causing a volley of debug output - when LD_DEBUG=symbols. */ - foo (); - - return 0; -} - -#define TEST_FUNCTION_ARGV do_test -#include <support/test-driver.c> diff --git a/elf/tst-order-a1.c b/elf/tst-order-a1.c deleted file mode 100644 index f161257142..0000000000 --- a/elf/tst-order-a1.c +++ /dev/null @@ -1,16 +0,0 @@ -#include <stdio.h> - -extern void start_a1( void ) __attribute__((constructor)); -extern void finish_a1( void ) __attribute__((destructor)); - -void -start_a1( void ) -{ - printf( "start_a1\n" ); -} - -void -finish_a1( void ) -{ - printf( "finish_a1\n" ); -} diff --git a/elf/tst-order-a2.c b/elf/tst-order-a2.c deleted file mode 100644 index a5a9b42ff6..0000000000 --- a/elf/tst-order-a2.c +++ /dev/null @@ -1,16 +0,0 @@ -#include <stdio.h> - -extern void start_a2( void ) __attribute__((constructor)); -extern void finish_a2( void ) __attribute__((destructor)); - -void -start_a2( void ) -{ - printf( "start_a2\n" ); -} - -void -finish_a2( void ) -{ - printf( "finish_a2\n" ); -} diff --git a/elf/tst-order-a3.c b/elf/tst-order-a3.c deleted file mode 100644 index 1c7f496e9a..0000000000 --- a/elf/tst-order-a3.c +++ /dev/null @@ -1,16 +0,0 @@ -#include <stdio.h> - -extern void start_a3( void ) __attribute__((constructor)); -extern void finish_a3( void ) __attribute__((destructor)); - -void -start_a3( void ) -{ - printf( "start_a3\n" ); -} - -void -finish_a3( void ) -{ - printf( "finish_a3\n" ); -} diff --git a/elf/tst-order-a4.c b/elf/tst-order-a4.c deleted file mode 100644 index 70b9f5e392..0000000000 --- a/elf/tst-order-a4.c +++ /dev/null @@ -1,16 +0,0 @@ -#include <stdio.h> - -extern void start_a4( void ) __attribute__((constructor)); -extern void finish_a4( void ) __attribute__((destructor)); - -void -start_a4( void ) -{ - printf( "start_a4\n" ); -} - -void -finish_a4( void ) -{ - printf( "finish_a4\n" ); -} diff --git a/elf/tst-order-b1.c b/elf/tst-order-b1.c deleted file mode 100644 index 993ea3fe30..0000000000 --- a/elf/tst-order-b1.c +++ /dev/null @@ -1,16 +0,0 @@ -#include <stdio.h> - -extern void start_b1( void ) __attribute__((constructor)); -extern void finish_b1( void ) __attribute__((destructor)); - -void -start_b1( void ) -{ - printf( "start_b1\n" ); -} - -void -finish_b1( void ) -{ - printf( "finish_b1\n" ); -} diff --git a/elf/tst-order-b2.c b/elf/tst-order-b2.c deleted file mode 100644 index 3334dda0a9..0000000000 --- a/elf/tst-order-b2.c +++ /dev/null @@ -1,16 +0,0 @@ -#include <stdio.h> - -extern void start_b2( void ) __attribute__((constructor)); -extern void finish_b2( void ) __attribute__((destructor)); - -void -start_b2( void ) -{ - printf( "start_b2\n" ); -} - -void -finish_b2( void ) -{ - printf( "finish_b2\n" ); -} diff --git a/elf/tst-order-main.c b/elf/tst-order-main.c deleted file mode 100644 index 2a90130db6..0000000000 --- a/elf/tst-order-main.c +++ /dev/null @@ -1,12 +0,0 @@ -#include <stdio.h> -#include <unistd.h> -#include <stdlib.h> - -static int -do_test (void) -{ - printf( "main\n" ); - exit(EXIT_SUCCESS); -} - -#include <support/test-driver.c> diff --git a/elf/tst-pathopt.c b/elf/tst-pathopt.c deleted file mode 100644 index e2c96fbc72..0000000000 --- a/elf/tst-pathopt.c +++ /dev/null @@ -1,41 +0,0 @@ -#include <dlfcn.h> -#include <mcheck.h> -#include <stdio.h> -#include <stdlib.h> - - -static int -do_test (void) -{ - void *h; - int (*fp) (int); - int result; - - mtrace (); - - h = dlopen ("renamed.so", RTLD_LAZY); - if (h == NULL) - { - printf ("failed to load \"%s\": %s\n", "renamed.so", dlerror ()); - exit (1); - } - - fp = dlsym (h, "in_renamed"); - if (fp == NULL) - { - printf ("lookup of \"%s\" failed: %s\n", "in_renamed", dlerror ()); - exit (1); - } - - result = fp (10); - - if (dlclose (h) != 0) - { - printf ("failed to close \"%s\": %s\n", "renamed.so", dlerror ()); - exit (1); - } - - return result; -} - -#include <support/test-driver.c> diff --git a/elf/tst-pathopt.sh b/elf/tst-pathopt.sh deleted file mode 100755 index 4183a697dc..0000000000 --- a/elf/tst-pathopt.sh +++ /dev/null @@ -1,39 +0,0 @@ -#!/bin/sh -# Test lookup path optimization. -# Copyright (C) 2000-2017 Free Software Foundation, Inc. -# This file is part of the GNU C Library. - -# The GNU C Library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. - -# The GNU C Library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. - -# You should have received a copy of the GNU Lesser General Public -# License along with the GNU C Library; if not, see -# <http://www.gnu.org/licenses/>. - -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 -test -d ${common_objpfx}elf/for-renamed || - mkdir ${common_objpfx}elf/for-renamed - -cp ${common_objpfx}elf/pathoptobj.so ${common_objpfx}elf/for-renamed/renamed.so - -${test_wrapper_env} \ -${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 - -exit $? diff --git a/elf/tst-pie1.c b/elf/tst-pie1.c deleted file mode 100644 index 75d941f21f..0000000000 --- a/elf/tst-pie1.c +++ /dev/null @@ -1,5 +0,0 @@ -int -foo (void) -{ - return 34; -} diff --git a/elf/tst-pie2.c b/elf/tst-pie2.c deleted file mode 100644 index 32943bbc1a..0000000000 --- a/elf/tst-pie2.c +++ /dev/null @@ -1,40 +0,0 @@ -/* Test case for BZ #16381 - - Copyright (C) 2014-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - - -#include <assert.h> - -static int g; - -void init_g (void) __attribute__((constructor)); - -void -init_g (void) -{ - assert (g == 0); - g += 1; -} - -static int -do_test (void) -{ - return 0; -} - -#include <support/test-driver.c> diff --git a/elf/tst-piemod1.c b/elf/tst-piemod1.c deleted file mode 100644 index 72d7e0a187..0000000000 --- a/elf/tst-piemod1.c +++ /dev/null @@ -1,22 +0,0 @@ -#include <stdio.h> - -int -foo (void) -{ - return 21; -} - -static int -do_test (void) -{ - int val = foo (); - if (val != 34) - { - printf ("foo () returned %d\n", val); - return 1; - } - - return 0; -} - -#include <support/test-driver.c> diff --git a/elf/tst-prelink.c b/elf/tst-prelink.c deleted file mode 100644 index 7435c321d3..0000000000 --- a/elf/tst-prelink.c +++ /dev/null @@ -1,29 +0,0 @@ -/* Test the output from the environment variable, LD_TRACE_PRELINKING, - for prelink. - Copyright (C) 2015-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -#include <stdio.h> - -static int -do_test (void) -{ - fprintf (stdout, "hello\n"); - return 0; -} - -#include <support/test-driver.c> diff --git a/elf/tst-prelink.exp b/elf/tst-prelink.exp deleted file mode 100644 index b35b4c9705..0000000000 --- a/elf/tst-prelink.exp +++ /dev/null @@ -1 +0,0 @@ -/0 stdout diff --git a/elf/tst-protected1a.c b/elf/tst-protected1a.c deleted file mode 100644 index 4267b951c4..0000000000 --- a/elf/tst-protected1a.c +++ /dev/null @@ -1,234 +0,0 @@ -/* 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-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -/* 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; - -/* This defines the `main' function and some more. */ -#include <support/test-driver.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 deleted file mode 100644 index 9fd695bffa..0000000000 --- a/elf/tst-protected1b.c +++ /dev/null @@ -1,240 +0,0 @@ -/* 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-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -/* 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; - -/* This defines the `main' function and some more. */ -#include <support/test-driver.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 deleted file mode 100644 index a47d65f6b1..0000000000 --- a/elf/tst-protected1mod.h +++ /dev/null @@ -1,41 +0,0 @@ -/* Copyright (C) 2015-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -/* 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 deleted file mode 100644 index aca4fc82a8..0000000000 --- a/elf/tst-protected1moda.c +++ /dev/null @@ -1,92 +0,0 @@ -/* Copyright (C) 2015-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -#include "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 deleted file mode 100644 index 5036b6c3e7..0000000000 --- a/elf/tst-protected1modb.c +++ /dev/null @@ -1,62 +0,0 @@ -/* Copyright (C) 2015-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -#include <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-static.c b/elf/tst-ptrguard1-static.c deleted file mode 100644 index 7aff3b7b5d..0000000000 --- a/elf/tst-ptrguard1-static.c +++ /dev/null @@ -1 +0,0 @@ -#include "tst-ptrguard1.c" diff --git a/elf/tst-ptrguard1.c b/elf/tst-ptrguard1.c deleted file mode 100644 index 8ea65bb0bb..0000000000 --- a/elf/tst-ptrguard1.c +++ /dev/null @@ -1,217 +0,0 @@ -/* Copyright (C) 2013-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -#include <errno.h> -#include <stdbool.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/wait.h> -#include <stackguard-macros.h> -#include <tls.h> -#include <unistd.h> - -#ifndef _GNU_SOURCE -#define _GNU_SOURCE -#endif -/* Requires _GNU_SOURCE */ -#include <getopt.h> - -#ifndef POINTER_CHK_GUARD -extern uintptr_t __pointer_chk_guard; -# define POINTER_CHK_GUARD __pointer_chk_guard -#endif - -static const char *command; -static bool child; -static uintptr_t ptr_chk_guard_copy; -static bool ptr_chk_guard_copy_set; -static int fds[2]; - -static void __attribute__ ((constructor)) -con (void) -{ - ptr_chk_guard_copy = POINTER_CHK_GUARD; - ptr_chk_guard_copy_set = true; -} - -static int -uintptr_t_cmp (const void *a, const void *b) -{ - if (*(uintptr_t *) a < *(uintptr_t *) b) - return 1; - if (*(uintptr_t *) a > *(uintptr_t *) b) - return -1; - return 0; -} - -static int -do_test (void) -{ - if (!ptr_chk_guard_copy_set) - { - puts ("constructor has not been run"); - return 1; - } - - if (ptr_chk_guard_copy != POINTER_CHK_GUARD) - { - puts ("POINTER_CHK_GUARD changed between constructor and do_test"); - return 1; - } - - if (child) - { - write (2, &ptr_chk_guard_copy, sizeof (ptr_chk_guard_copy)); - return 0; - } - - if (command == NULL) - { - puts ("missing --command or --child argument"); - return 1; - } - -#define N 16 - uintptr_t child_ptr_chk_guards[N + 1]; - child_ptr_chk_guards[N] = ptr_chk_guard_copy; - int i; - for (i = 0; i < N; ++i) - { - if (pipe (fds) < 0) - { - printf ("couldn't create pipe: %m\n"); - return 1; - } - - pid_t pid = fork (); - if (pid < 0) - { - printf ("fork failed: %m\n"); - return 1; - } - - if (!pid) - { - if (ptr_chk_guard_copy != POINTER_CHK_GUARD) - { - puts ("POINTER_CHK_GUARD changed after fork"); - exit (1); - } - - close (fds[0]); - close (2); - dup2 (fds[1], 2); - close (fds[1]); - - system (command); - exit (0); - } - - close (fds[1]); - - if (TEMP_FAILURE_RETRY (read (fds[0], &child_ptr_chk_guards[i], - sizeof (uintptr_t))) != sizeof (uintptr_t)) - { - puts ("could not read ptr_chk_guard value from child"); - return 1; - } - - close (fds[0]); - - pid_t termpid; - int status; - termpid = TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)); - if (termpid == -1) - { - printf ("waitpid failed: %m\n"); - return 1; - } - else if (termpid != pid) - { - printf ("waitpid returned %ld != %ld\n", - (long int) termpid, (long int) pid); - return 1; - } - else if (!WIFEXITED (status) || WEXITSTATUS (status)) - { - puts ("child hasn't exited with exit status 0"); - return 1; - } - } - - qsort (child_ptr_chk_guards, N + 1, sizeof (uintptr_t), uintptr_t_cmp); - - /* The default pointer guard is the same as the default stack guard. - They are only set to default if dl_random is NULL. */ - uintptr_t default_guard = 0; - unsigned char *p = (unsigned char *) &default_guard; - p[sizeof (uintptr_t) - 1] = 255; - p[sizeof (uintptr_t) - 2] = '\n'; - p[0] = 0; - - /* Test if the pointer guard canaries are either randomized, - or equal to the default pointer guard value. - Even with randomized pointer guards it might happen - that the random number generator generates the same - values, but if that happens in more than half from - the 16 runs, something is very wrong. */ - int ndifferences = 0; - int ndefaults = 0; - for (i = 0; i < N; ++i) - { - if (child_ptr_chk_guards[i] != child_ptr_chk_guards[i+1]) - ndifferences++; - else if (child_ptr_chk_guards[i] == default_guard) - ndefaults++; - } - - printf ("differences %d defaults %d\n", ndifferences, ndefaults); - - if (ndifferences < N / 2 && ndefaults < N / 2) - { - puts ("pointer guard values are not randomized enough"); - puts ("nor equal to the default value"); - return 1; - } - - return 0; -} - -#define OPT_COMMAND 10000 -#define OPT_CHILD 10001 -#define CMDLINE_OPTIONS \ - { "command", required_argument, NULL, OPT_COMMAND }, \ - { "child", no_argument, NULL, OPT_CHILD }, - -static void __attribute((used)) -cmdline_process_function (int c) -{ - switch (c) - { - case OPT_COMMAND: - command = optarg; - break; - case OPT_CHILD: - child = true; - break; - } -} - -#define CMDLINE_PROCESS cmdline_process_function - -#include <support/test-driver.c> diff --git a/elf/tst-relsort1.c b/elf/tst-relsort1.c deleted file mode 100644 index 775c968e1f..0000000000 --- a/elf/tst-relsort1.c +++ /dev/null @@ -1,18 +0,0 @@ -#include <dlfcn.h> -#include <stdio.h> - - -static int -do_test (void) -{ - const char lib[] = "$ORIGIN/tst-relsort1mod1.so"; - void *h = dlopen (lib, RTLD_NOW); - if (h == NULL) - { - puts (dlerror ()); - return 1; - } - return 0; -} - -#include <support/test-driver.c> diff --git a/elf/tst-relsort1mod1.c b/elf/tst-relsort1mod1.c deleted file mode 100644 index 9e4a94321d..0000000000 --- a/elf/tst-relsort1mod1.c +++ /dev/null @@ -1,7 +0,0 @@ -extern int foo (double); - -int -bar (void) -{ - return foo (1.2); -} diff --git a/elf/tst-relsort1mod2.c b/elf/tst-relsort1mod2.c deleted file mode 100644 index a2c3e551e4..0000000000 --- a/elf/tst-relsort1mod2.c +++ /dev/null @@ -1,7 +0,0 @@ -#include <math.h> - -int -foo (double d) -{ - return floor (d) != 0.0; -} diff --git a/elf/tst-rtld-load-self.sh b/elf/tst-rtld-load-self.sh deleted file mode 100755 index e05f6d145f..0000000000 --- a/elf/tst-rtld-load-self.sh +++ /dev/null @@ -1,49 +0,0 @@ -#!/bin/sh -# Test how rtld loads itself. -# Copyright (C) 2012-2017 Free Software Foundation, Inc. -# This file is part of the GNU C Library. -# - -# The GNU C Library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. - -# The GNU C Library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. - -# You should have received a copy of the GNU Lesser General Public -# License along with the GNU C Library; if not, see -# <http://www.gnu.org/licenses/>. - -set -e - -rtld=$1 -test_wrapper=$2 -test_wrapper_env=$3 -result=0 - -echo '# normal mode' -${test_wrapper} $rtld $rtld 2>&1 && rc=0 || rc=$? -echo "# exit status $rc" -test $rc -le 127 || result=1 - -echo '# list mode' -${test_wrapper} $rtld --list $rtld 2>&1 && rc=0 || rc=$? -echo "# exit status $rc" -test $rc -eq 0 || result=1 - -echo '# verify mode' -${test_wrapper} $rtld --verify $rtld 2>&1 && rc=0 || rc=$? -echo "# exit status $rc" -test $rc -eq 2 || result=1 - -echo '# trace mode' -${test_wrapper_env} LD_TRACE_LOADED_OBJECTS=1 \ - $rtld $rtld 2>&1 && rc=0 || rc=$? -echo "# exit status $rc" -test $rc -eq 0 || result=1 - -exit $result diff --git a/elf/tst-stackguard1-static.c b/elf/tst-stackguard1-static.c deleted file mode 100644 index db1e21554d..0000000000 --- a/elf/tst-stackguard1-static.c +++ /dev/null @@ -1 +0,0 @@ -#include "tst-stackguard1.c" diff --git a/elf/tst-stackguard1.c b/elf/tst-stackguard1.c deleted file mode 100644 index 78e33c7083..0000000000 --- a/elf/tst-stackguard1.c +++ /dev/null @@ -1,205 +0,0 @@ -/* Copyright (C) 2005-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Jakub Jelinek <jakub@redhat.com>, 2005. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -#include <errno.h> -#include <getopt.h> -#include <stdbool.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/wait.h> -#include <stackguard-macros.h> -#include <tls.h> -#include <unistd.h> - -static const char *command; -static bool child; -static uintptr_t stack_chk_guard_copy; -static bool stack_chk_guard_copy_set; -static int fds[2]; - -static void __attribute__ ((constructor)) -con (void) -{ - stack_chk_guard_copy = STACK_CHK_GUARD; - stack_chk_guard_copy_set = true; -} - -static int -uintptr_t_cmp (const void *a, const void *b) -{ - if (*(uintptr_t *) a < *(uintptr_t *) b) - return 1; - if (*(uintptr_t *) a > *(uintptr_t *) b) - return -1; - return 0; -} - -static int -do_test (void) -{ - if (!stack_chk_guard_copy_set) - { - puts ("constructor has not been run"); - return 1; - } - - if (stack_chk_guard_copy != STACK_CHK_GUARD) - { - puts ("STACK_CHK_GUARD changed between constructor and do_test"); - return 1; - } - - if (child) - { - write (2, &stack_chk_guard_copy, sizeof (stack_chk_guard_copy)); - return 0; - } - - if (command == NULL) - { - puts ("missing --command or --child argument"); - return 1; - } - -#define N 16 - uintptr_t child_stack_chk_guards[N + 1]; - child_stack_chk_guards[N] = stack_chk_guard_copy; - int i; - for (i = 0; i < N; ++i) - { - if (pipe (fds) < 0) - { - printf ("couldn't create pipe: %m\n"); - return 1; - } - - pid_t pid = fork (); - if (pid < 0) - { - printf ("fork failed: %m\n"); - return 1; - } - - if (!pid) - { - if (stack_chk_guard_copy != STACK_CHK_GUARD) - { - puts ("STACK_CHK_GUARD changed after fork"); - exit (1); - } - - close (fds[0]); - close (2); - dup2 (fds[1], 2); - close (fds[1]); - - system (command); - exit (0); - } - - close (fds[1]); - - if (TEMP_FAILURE_RETRY (read (fds[0], &child_stack_chk_guards[i], - sizeof (uintptr_t))) != sizeof (uintptr_t)) - { - puts ("could not read stack_chk_guard value from child"); - return 1; - } - - close (fds[0]); - - pid_t termpid; - int status; - termpid = TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)); - if (termpid == -1) - { - printf ("waitpid failed: %m\n"); - return 1; - } - else if (termpid != pid) - { - printf ("waitpid returned %ld != %ld\n", - (long int) termpid, (long int) pid); - return 1; - } - else if (!WIFEXITED (status) || WEXITSTATUS (status)) - { - puts ("child hasn't exited with exit status 0"); - return 1; - } - } - - qsort (child_stack_chk_guards, N + 1, sizeof (uintptr_t), uintptr_t_cmp); - - uintptr_t default_guard = 0; - unsigned char *p = (unsigned char *) &default_guard; - p[sizeof (uintptr_t) - 1] = 255; - p[sizeof (uintptr_t) - 2] = '\n'; - p[0] = 0; - - /* Test if the stack guard canaries are either randomized, - or equal to the default stack guard canary value. - Even with randomized stack guards it might happen - that the random number generator generates the same - values, but if that happens in more than half from - the 16 runs, something is very wrong. */ - int ndifferences = 0; - int ndefaults = 0; - for (i = 0; i < N; ++i) - { - if (child_stack_chk_guards[i] != child_stack_chk_guards[i+1]) - ndifferences++; - else if (child_stack_chk_guards[i] == default_guard) - ndefaults++; - } - - printf ("differences %d defaults %d\n", ndifferences, ndefaults); - - if (ndifferences < N / 2 && ndefaults < N / 2) - { - puts ("stack guard canaries are not randomized enough"); - puts ("nor equal to the default canary value"); - return 1; - } - - return 0; -} - -#define OPT_COMMAND 10000 -#define OPT_CHILD 10001 -#define CMDLINE_OPTIONS \ - { "command", required_argument, NULL, OPT_COMMAND }, \ - { "child", no_argument, NULL, OPT_CHILD }, - -static void __attribute__((used)) -cmdline_process_function (int c) -{ - switch (c) - { - case OPT_COMMAND: - command = optarg; - break; - case OPT_CHILD: - child = true; - break; - } -} -#define CMDLINE_PROCESS cmdline_process_function - -#include <support/test-driver.c> diff --git a/elf/tst-thrlock.c b/elf/tst-thrlock.c deleted file mode 100644 index 1beffc3861..0000000000 --- a/elf/tst-thrlock.c +++ /dev/null @@ -1,58 +0,0 @@ -#include <dlfcn.h> -#include <pthread.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <gnu/lib-names.h> - -static void * -tf (void *arg) -{ - void *h = dlopen (LIBM_SO, RTLD_LAZY); - if (h == NULL) - { - printf ("dlopen failed: %s\n", dlerror ()); - exit (1); - } - if (dlsym (h, "sin") == NULL) - { - printf ("dlsym failed: %s\n", dlerror ()); - exit (1); - } - if (dlclose (h) != 0) - { - printf ("dlclose failed: %s\n", dlerror ()); - exit (1); - } - return NULL; -} - - -static int -do_test (void) -{ -#define N 10 - pthread_t th[N]; - for (int i = 0; i < N; ++i) - { - int e = pthread_create (&th[i], NULL, tf, NULL); - if (e != 0) - { - printf ("pthread_create failed with %d (%s)\n", e, strerror (e)); - return 1; - } - } - for (int i = 0; i < N; ++i) - { - void *res; - int e = pthread_join (th[i], &res); - if (e != 0 || res != NULL) - { - puts ("thread failed"); - return 1; - } - } - return 0; -} - -#include <support/test-driver.c> diff --git a/elf/tst-tls-dlinfo.c b/elf/tst-tls-dlinfo.c deleted file mode 100644 index 7d2b42e2ab..0000000000 --- a/elf/tst-tls-dlinfo.c +++ /dev/null @@ -1,85 +0,0 @@ -#include <dlfcn.h> -#include <stdio.h> -#include <stdlib.h> - - -static int -do_test (void) -{ - static const char modname[] = "tst-tlsmod2.so"; - int result = 0; - int *foop; - int (*fp) (int, int *); - void *h; - - h = dlopen (modname, RTLD_LAZY); - if (h == NULL) - { - printf ("cannot open '%s': %s\n", modname, dlerror ()); - exit (1); - } - - fp = dlsym (h, "in_dso"); - if (fp == NULL) - { - printf ("cannot get symbol 'in_dso': %s\n", dlerror ()); - exit (1); - } - - size_t modid = -1; - if (dlinfo (h, RTLD_DI_TLS_MODID, &modid)) - { - printf ("dlinfo RTLD_DI_TLS_MODID failed: %s\n", dlerror ()); - result = 1; - } - else - printf ("dlinfo says TLS module ID %Zu\n", modid); - - void *block; - if (dlinfo (h, RTLD_DI_TLS_DATA, &block)) - { - printf ("dlinfo RTLD_DI_TLS_DATA failed: %s\n", dlerror ()); - result = 1; - } - else if (block != NULL) - { - printf ("dlinfo RTLD_DI_TLS_DATA says %p but should be unallocated\n", - block); - result = 1; - } - - result |= fp (0, NULL); - - foop = dlsym (h, "foo"); - if (foop == NULL) - { - printf ("cannot get symbol 'foo' the second time: %s\n", dlerror ()); - exit (1); - } - if (*foop != 16) - { - puts ("foo != 16"); - result = 1; - } - - /* Now the module's TLS block has been used and should appear. */ - if (dlinfo (h, RTLD_DI_TLS_DATA, &block)) - { - printf ("dlinfo RTLD_DI_TLS_DATA failed the second time: %s\n", - dlerror ()); - result = 1; - } - else if (block != foop) - { - printf ("dlinfo RTLD_DI_TLS_DATA says %p but should be %p\n", - block, foop); - result = 1; - } - - dlclose (h); - - return result; -} - - -#include <support/test-driver.c> diff --git a/elf/tst-tls-manydynamic.c b/elf/tst-tls-manydynamic.c deleted file mode 100644 index b072d0be68..0000000000 --- a/elf/tst-tls-manydynamic.c +++ /dev/null @@ -1,151 +0,0 @@ -/* Test with many dynamic TLS variables. - Copyright (C) 2016-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -/* This test intends to exercise dynamic TLS variable allocation. It - achieves this by combining dlopen (to avoid static TLS allocation - after static TLS resizing), many DSOs with a large variable (to - exceed the static TLS reserve), and an already-running thread (to - force full dynamic TLS initialization). */ - -#include "tst-tls-manydynamic.h" - -#include <errno.h> -#include <dlfcn.h> -#include <pthread.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -static int do_test (void); -#include <support/xthread.h> -#include <support/test-driver.c> - -void *handles[COUNT]; -set_value_func set_value_funcs[COUNT]; -get_value_func get_value_funcs[COUNT]; - -static void -init_functions (void) -{ - for (int i = 0; i < COUNT; ++i) - { - /* Open the module. */ - { - char soname[100]; - snprintf (soname, sizeof (soname), "tst-tls-manydynamic%02dmod.so", i); - handles[i] = dlopen (soname, RTLD_LAZY); - if (handles[i] == NULL) - { - printf ("error: dlopen failed: %s\n", dlerror ()); - exit (1); - } - } - - /* Obtain the setter function. */ - { - char fname[100]; - snprintf (fname, sizeof (fname), "set_value_%02d", i); - void *func = dlsym (handles[i], fname); - if (func == NULL) - { - printf ("error: dlsym: %s\n", dlerror ()); - exit (1); - } - set_value_funcs[i] = func; - } - - /* Obtain the getter function. */ - { - char fname[100]; - snprintf (fname, sizeof (fname), "get_value_%02d", i); - void *func = dlsym (handles[i], fname); - if (func == NULL) - { - printf ("error: dlsym: %s\n", dlerror ()); - exit (1); - } - get_value_funcs[i] = func; - } - } -} - -static pthread_barrier_t barrier; - -/* Running thread which forces real TLS initialization. */ -static void * -blocked_thread_func (void *closure) -{ - xpthread_barrier_wait (&barrier); - - /* TLS test runs here in the main thread. */ - - xpthread_barrier_wait (&barrier); - return NULL; -} - -static int -do_test (void) -{ - { - int ret = pthread_barrier_init (&barrier, NULL, 2); - if (ret != 0) - { - errno = ret; - printf ("error: pthread_barrier_init: %m\n"); - exit (1); - } - } - - pthread_t blocked_thread = xpthread_create (NULL, blocked_thread_func, NULL); - xpthread_barrier_wait (&barrier); - - init_functions (); - - struct value values[COUNT]; - /* Initialze the TLS variables. */ - for (int i = 0; i < COUNT; ++i) - { - for (int j = 0; j < PER_VALUE_COUNT; ++j) - values[i].num[j] = rand (); - set_value_funcs[i] (&values[i]); - } - - /* Read back their values to check that they do not overlap. */ - for (int i = 0; i < COUNT; ++i) - { - struct value actual; - get_value_funcs[i] (&actual); - - for (int j = 0; j < PER_VALUE_COUNT; ++j) - if (actual.num[j] != values[i].num[j]) - { - printf ("error: mismatch at variable %d/%d: %d != %d\n", - i, j, actual.num[j], values[i].num[j]); - exit (1); - } - } - - xpthread_barrier_wait (&barrier); - xpthread_join (blocked_thread); - - /* Close the modules. */ - for (int i = 0; i < COUNT; ++i) - dlclose (handles[i]); - - return 0; -} diff --git a/elf/tst-tls-manydynamic.h b/elf/tst-tls-manydynamic.h deleted file mode 100644 index 13fac4e7e8..0000000000 --- a/elf/tst-tls-manydynamic.h +++ /dev/null @@ -1,44 +0,0 @@ -/* Interfaces for test with many dynamic TLS variables. - Copyright (C) 2016-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -#ifndef TST_TLS_MANYDYNAMIC_H -#define TST_TLS_MANYDYNAMIC_H - -enum - { - /* This many TLS variables (and modules) are defined. */ - COUNT = 100, - - /* Number of elements in the TLS variable. */ - PER_VALUE_COUNT = 1, - }; - -/* The TLS variables are of this type. We use a larger type to ensure - that we can reach the static TLS limit with COUNT variables. */ -struct value -{ - int num[PER_VALUE_COUNT]; -}; - -/* Set the TLS variable defined in the module. */ -typedef void (*set_value_func) (const struct value *); - -/* Read the TLS variable defined in the module. */ -typedef void (*get_value_func) (struct value *); - -#endif /* TST_TLS_MANYDYNAMICMOD_H */ diff --git a/elf/tst-tls-manydynamicmod.c b/elf/tst-tls-manydynamicmod.c deleted file mode 100644 index edfaeef7f3..0000000000 --- a/elf/tst-tls-manydynamicmod.c +++ /dev/null @@ -1,36 +0,0 @@ -/* Module for test with many dynamic TLS variables. - Copyright (C) 2016-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -/* This file is parameterized by macros NAME, SETTER, GETTER, which - are set form the Makefile. */ - -#include "tst-tls-manydynamic.h" - -__thread struct value NAME; - -void -SETTER (const struct value *value) -{ - NAME = *value; -} - -void -GETTER (struct value *value) -{ - *value = NAME; -} diff --git a/elf/tst-tls1-static.c b/elf/tst-tls1-static.c deleted file mode 100644 index a01008073b..0000000000 --- a/elf/tst-tls1-static.c +++ /dev/null @@ -1 +0,0 @@ -#include "tst-tls1.c" diff --git a/elf/tst-tls1.c b/elf/tst-tls1.c deleted file mode 100644 index c31da56ce9..0000000000 --- a/elf/tst-tls1.c +++ /dev/null @@ -1,82 +0,0 @@ -/* glibc test for TLS in ld.so. */ -#include <stdio.h> - -#include "tls-macros.h" - - -/* Two common 'int' variables in TLS. */ -COMMON_INT_DEF(foo); -COMMON_INT_DEF(bar); - - -static int -do_test (void) -{ - int result = 0; - int *ap, *bp; - - - /* Set the variable using the local exec model. */ - puts ("set bar to 1 (LE)"); - ap = TLS_LE (bar); - *ap = 1; - - - /* Get variables using initial exec model. */ - fputs ("get sum of foo and bar (IE)", stdout); - ap = TLS_IE (foo); - bp = TLS_IE (bar); - printf (" = %d\n", *ap + *bp); - result |= *ap + *bp != 1; - if (*ap != 0) - { - printf ("foo = %d\n", *ap); - result = 1; - } - if (*bp != 1) - { - printf ("bar = %d\n", *bp); - result = 1; - } - - - /* Get variables using local dynamic model. */ - fputs ("get sum of foo and bar (LD)", stdout); - ap = TLS_LD (foo); - bp = TLS_LD (bar); - printf (" = %d\n", *ap + *bp); - result |= *ap + *bp != 1; - if (*ap != 0) - { - printf ("foo = %d\n", *ap); - result = 1; - } - if (*bp != 1) - { - printf ("bar = %d\n", *bp); - result = 1; - } - - - /* Get variables using generic dynamic model. */ - fputs ("get sum of foo and bar (GD)", stdout); - ap = TLS_GD (foo); - bp = TLS_GD (bar); - printf (" = %d\n", *ap + *bp); - result |= *ap + *bp != 1; - if (*ap != 0) - { - printf ("foo = %d\n", *ap); - result = 1; - } - if (*bp != 1) - { - printf ("bar = %d\n", *bp); - result = 1; - } - - return result; -} - - -#include <support/test-driver.c> diff --git a/elf/tst-tls10.c b/elf/tst-tls10.c deleted file mode 100644 index d9611aac6d..0000000000 --- a/elf/tst-tls10.c +++ /dev/null @@ -1,39 +0,0 @@ -#include "tst-tls10.h" - -__thread int dummy __attribute__((visibility ("hidden"))) = 12; -__thread struct A local = { 1, 2, 3 }; - -#define CHECK(N, S) \ - p = f##N##a (); \ - if (p->a != S || p->b != S + 1 || p->c != S + 2) \ - abort () - -static int -do_test (void) -{ - struct A *p; - if (local.a != 1 || local.b != 2 || local.c != 3) - abort (); - if (a1.a != 4 || a1.b != 5 || a1.c != 6) - abort (); - if (a2.a != 22 || a2.b != 23 || a2.c != 24) - abort (); - if (a3.a != 10 || a3.b != 11 || a3.c != 12) - abort (); - if (a4.a != 25 || a4.b != 26 || a4.c != 27) - abort (); - check1 (); - check2 (); - if (f1a () != &a1 || f2a () != &a2 || f3a () != &a3 || f4a () != &a4) - abort (); - CHECK (5, 16); - CHECK (6, 19); - if (f7a () != &a2 || f8a () != &a4) - abort (); - CHECK (9, 28); - CHECK (10, 31); - - exit (0); -} - -#include <support/test-driver.c> diff --git a/elf/tst-tls10.h b/elf/tst-tls10.h deleted file mode 100644 index 7c8c6a6391..0000000000 --- a/elf/tst-tls10.h +++ /dev/null @@ -1,32 +0,0 @@ -#include <stdlib.h> - -struct A -{ - char a; - int b; - long long c; -}; - -extern __thread struct A a1, a2, a3, a4; -extern struct A *f1a (void); -extern struct A *f2a (void); -extern struct A *f3a (void); -extern struct A *f4a (void); -extern struct A *f5a (void); -extern struct A *f6a (void); -extern struct A *f7a (void); -extern struct A *f8a (void); -extern struct A *f9a (void); -extern struct A *f10a (void); -extern int f1b (void); -extern int f2b (void); -extern int f3b (void); -extern int f4b (void); -extern int f5b (void); -extern int f6b (void); -extern int f7b (void); -extern int f8b (void); -extern int f9b (void); -extern int f10b (void); -extern void check1 (void); -extern void check2 (void); diff --git a/elf/tst-tls11.c b/elf/tst-tls11.c deleted file mode 100644 index a5c3dd70b0..0000000000 --- a/elf/tst-tls11.c +++ /dev/null @@ -1,28 +0,0 @@ -#include "tst-tls10.h" - -#define CHECK(N, S) \ - p = f##N##a (); \ - if (p->a != S || p->b != S + 1 || p->c != S + 2) \ - abort () - -static int -do_test (void) -{ - struct A *p; - check1 (); - check2 (); - CHECK (1, 4); - CHECK (2, 22); - CHECK (3, 10); - CHECK (4, 25); - CHECK (5, 16); - CHECK (6, 19); - CHECK (7, 22); - CHECK (8, 25); - CHECK (9, 28); - CHECK (10, 31); - - exit (0); -} - -#include <support/test-driver.c> diff --git a/elf/tst-tls12.c b/elf/tst-tls12.c deleted file mode 100644 index ccd5f8b43e..0000000000 --- a/elf/tst-tls12.c +++ /dev/null @@ -1,19 +0,0 @@ -#include "tst-tls10.h" - -#define CHECK(N, S) \ - p = &a##N; \ - if (p->a != S || p->b != S + 1 || p->c != S + 2) \ - abort () - -static int -do_test (void) -{ - struct A *p; - check1 (); - CHECK (1, 4); - CHECK (2, 7); - - exit (0); -} - -#include <support/test-driver.c> diff --git a/elf/tst-tls13.c b/elf/tst-tls13.c deleted file mode 100644 index b1d303310f..0000000000 --- a/elf/tst-tls13.c +++ /dev/null @@ -1,28 +0,0 @@ -/* Check unloading modules with data in static TLS block. */ -#include <dlfcn.h> -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> - - -static int -do_test (void) -{ - for (int i = 0; i < 1000;) - { - printf ("round %d\n",++i); - - void *h = dlopen ("$ORIGIN/tst-tlsmod13a.so", RTLD_LAZY); - if (h == NULL) - { - printf ("cannot load: %s\n", dlerror ()); - exit (1); - } - - dlclose (h); - } - - return 0; -} - -#include <support/test-driver.c> diff --git a/elf/tst-tls14.c b/elf/tst-tls14.c deleted file mode 100644 index a6a79ef24f..0000000000 --- a/elf/tst-tls14.c +++ /dev/null @@ -1,54 +0,0 @@ -/* Check alignment of TLS variable. */ -#include <dlfcn.h> -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> - -#define AL 4096 -struct foo -{ - int i; -} __attribute ((aligned (AL))); - -static __thread struct foo f; -static struct foo g; - - -extern int in_dso1 (void); - - -static int -do_test (void) -{ - int result = 0; - - int fail = (((uintptr_t) &f) & (AL - 1)) != 0; - printf ("&f = %p %s\n", &f, fail ? "FAIL" : "OK"); - result |= fail; - - fail = (((uintptr_t) &g) & (AL - 1)) != 0; - printf ("&g = %p %s\n", &g, fail ? "FAIL" : "OK"); - result |= fail; - - result |= in_dso1 (); - - void *h = dlopen ("tst-tlsmod14b.so", RTLD_LAZY); - if (h == NULL) - { - printf ("cannot open tst-tlsmod14b.so: %m\n"); - exit (1); - } - - int (*fp) (void) = (int (*) (void)) dlsym (h, "in_dso2"); - if (fp == NULL) - { - puts ("cannot find in_dso2"); - exit (1); - } - - result |= fp (); - - return result; -} - -#include <support/test-driver.c> diff --git a/elf/tst-tls15.c b/elf/tst-tls15.c deleted file mode 100644 index db2a4f4b77..0000000000 --- a/elf/tst-tls15.c +++ /dev/null @@ -1,32 +0,0 @@ -#include <dlfcn.h> -#include <stdlib.h> -#include <stdio.h> - -static int -do_test (void) -{ - void *h = dlopen ("tst-tlsmod15a.so", RTLD_NOW); - if (h != NULL) - { - puts ("unexpectedly succeeded to open tst-tlsmod15a.so"); - exit (1); - } - - h = dlopen ("tst-tlsmod15b.so", RTLD_NOW); - if (h == NULL) - { - puts ("failed to open tst-tlsmod15b.so"); - exit (1); - } - - int (*fp) (void) = (int (*) (void)) dlsym (h, "in_dso"); - if (fp == NULL) - { - puts ("cannot find in_dso"); - exit (1); - } - - return fp (); -} - -#include <support/test-driver.c> diff --git a/elf/tst-tls16.c b/elf/tst-tls16.c deleted file mode 100644 index f2830b8a4f..0000000000 --- a/elf/tst-tls16.c +++ /dev/null @@ -1,52 +0,0 @@ -#include <dlfcn.h> -#include <stdlib.h> -#include <stdio.h> - -static int -do_test (void) -{ - void *h = dlopen ("tst-tlsmod16a.so", RTLD_LAZY | RTLD_GLOBAL); - if (h == NULL) - { - puts ("unexpectedly failed to open tst-tlsmod16a.so"); - exit (1); - } - - void *p = dlsym (h, "tlsvar"); - - /* This dlopen should indeed fail, because tlsvar was assigned to - dynamic TLS, and the new module requests it to be in static TLS. - However, there's a possibility that dlopen succeeds if the - variable is, for whatever reason, assigned to static TLS, or if - the module fails to require static TLS, or even if TLS is not - supported. */ - h = dlopen ("tst-tlsmod16b.so", RTLD_NOW | RTLD_GLOBAL); - if (h == NULL) - { - return 0; - } - - puts ("unexpectedly succeeded to open tst-tlsmod16b.so"); - - - void *(*fp) (void) = (void *(*) (void)) dlsym (h, "in_dso"); - if (fp == NULL) - { - puts ("cannot find in_dso"); - exit (1); - } - - /* If the dlopen passes, at least make sure the address returned by - dlsym is the same as that returned by the initial-exec access. - If the variable was assigned to dynamic TLS during dlsym, this - portion will fail. */ - if (fp () != p) - { - puts ("returned values do not match"); - exit (1); - } - - return 0; -} - -#include <support/test-driver.c> diff --git a/elf/tst-tls17.c b/elf/tst-tls17.c deleted file mode 100644 index c2a972d3c4..0000000000 --- a/elf/tst-tls17.c +++ /dev/null @@ -1,28 +0,0 @@ -#include <dlfcn.h> -#include <stdlib.h> -#include <stdio.h> - -static int -do_test (void) -{ - void *h = dlopen ("tst-tlsmod17b.so", RTLD_LAZY); - if (h == NULL) - { - puts ("unexpectedly failed to open tst-tlsmod17b.so"); - exit (1); - } - - int (*fp) (void) = (int (*) (void)) dlsym (h, "tlsmod17b"); - if (fp == NULL) - { - puts ("cannot find tlsmod17b"); - exit (1); - } - - if (fp ()) - exit (1); - - return 0; -} - -#include <support/test-driver.c> diff --git a/elf/tst-tls18.c b/elf/tst-tls18.c deleted file mode 100644 index b705b61d60..0000000000 --- a/elf/tst-tls18.c +++ /dev/null @@ -1,37 +0,0 @@ -#include <dlfcn.h> -#include <stdlib.h> -#include <stdio.h> - -static int -do_test (void) -{ - char modname[sizeof "tst-tlsmod18aXX.so"]; - void *h[20]; - for (int i = 0; i < 20; i++) - { - snprintf (modname, sizeof modname, "tst-tlsmod18a%d.so", i); - h[i] = dlopen (modname, RTLD_LAZY); - if (h[i] == NULL) - { - printf ("unexpectedly failed to open %s", modname); - exit (1); - } - } - - for (int i = 0; i < 20; i++) - { - int (*fp) (void) = (int (*) (void)) dlsym (h[i], "test"); - if (fp == NULL) - { - printf ("cannot find test in tst-tlsmod18a%d.so", i); - exit (1); - } - - if (fp ()) - exit (1); - } - - return 0; -} - -#include <support/test-driver.c> diff --git a/elf/tst-tls19.c b/elf/tst-tls19.c deleted file mode 100644 index dd8ea42c3f..0000000000 --- a/elf/tst-tls19.c +++ /dev/null @@ -1,26 +0,0 @@ -// BZ 12453 -#include <stdio.h> -#include <dlfcn.h> - - -static int -do_test (void) -{ - void* dl = dlopen ("tst-tls19mod1.so", RTLD_LAZY | RTLD_GLOBAL); - if (dl == NULL) - { - printf ("Error loading tst-tls19mod1.so: %s\n", dlerror ()); - return 1; - } - - int (*fn) (void) = dlsym (dl, "foo"); - if (fn == NULL) - { - printf("Error obtaining symbol foo\n"); - return 1; - } - - return fn (); -} - -#include <support/test-driver.c> diff --git a/elf/tst-tls19mod1.c b/elf/tst-tls19mod1.c deleted file mode 100644 index 2790097ae5..0000000000 --- a/elf/tst-tls19mod1.c +++ /dev/null @@ -1,15 +0,0 @@ -#include <stdio.h> - -extern int bar (void); -extern int baz (void); - -int -foo (void) -{ - int v1 = bar (); - int v2 = baz (); - - printf ("bar=%d, baz=%d\n", v1, v2); - - return v1 != 666 || v2 != 42; -} diff --git a/elf/tst-tls19mod2.c b/elf/tst-tls19mod2.c deleted file mode 100644 index cae702f67c..0000000000 --- a/elf/tst-tls19mod2.c +++ /dev/null @@ -1,13 +0,0 @@ -static int __thread tbar __attribute__ ((tls_model ("initial-exec"))) = 666; - -void -setter (int a) -{ - tbar = a; -} - -int -bar (void) -{ - return tbar; -} diff --git a/elf/tst-tls19mod3.c b/elf/tst-tls19mod3.c deleted file mode 100644 index e7b28016b3..0000000000 --- a/elf/tst-tls19mod3.c +++ /dev/null @@ -1,16 +0,0 @@ -#include <stdio.h> - -static int __thread tbaz __attribute__ ((tls_model ("local-dynamic"))) = 42; - -void -setter2 (int a) -{ - tbaz = a; -} - -int -baz (void) -{ - printf ("&tbaz=%p\n", &tbaz); - return tbaz; -} diff --git a/elf/tst-tls2-static.c b/elf/tst-tls2-static.c deleted file mode 100644 index 55ffa57448..0000000000 --- a/elf/tst-tls2-static.c +++ /dev/null @@ -1 +0,0 @@ -#include "tst-tls2.c" diff --git a/elf/tst-tls2.c b/elf/tst-tls2.c deleted file mode 100644 index 963b8d6c88..0000000000 --- a/elf/tst-tls2.c +++ /dev/null @@ -1,82 +0,0 @@ -/* glibc test for TLS in ld.so. */ -#include <stdio.h> - -#include "tls-macros.h" - - -/* Two 'int' variables in TLS. */ -VAR_INT_DEF(foo); -VAR_INT_DEF(bar); - - -static int -do_test (void) -{ - int result = 0; - int *ap, *bp; - - - /* Set the variable using the local exec model. */ - puts ("set bar to 1 (LE)"); - ap = TLS_LE (bar); - *ap = 1; - - - /* Get variables using initial exec model. */ - fputs ("get sum of foo and bar (IE)", stdout); - ap = TLS_IE (foo); - bp = TLS_IE (bar); - printf (" = %d\n", *ap + *bp); - result |= *ap + *bp != 1; - if (*ap != 0) - { - printf ("foo = %d\n", *ap); - result = 1; - } - if (*bp != 1) - { - printf ("bar = %d\n", *bp); - result = 1; - } - - - /* Get variables using local dynamic model. */ - fputs ("get sum of foo and bar (LD)", stdout); - ap = TLS_LD (foo); - bp = TLS_LD (bar); - printf (" = %d\n", *ap + *bp); - result |= *ap + *bp != 1; - if (*ap != 0) - { - printf ("foo = %d\n", *ap); - result = 1; - } - if (*bp != 1) - { - printf ("bar = %d\n", *bp); - result = 1; - } - - - /* Get variables using generic dynamic model. */ - fputs ("get sum of foo and bar (GD)", stdout); - ap = TLS_GD (foo); - bp = TLS_GD (bar); - printf (" = %d\n", *ap + *bp); - result |= *ap + *bp != 1; - if (*ap != 0) - { - printf ("foo = %d\n", *ap); - result = 1; - } - if (*bp != 1) - { - printf ("bar = %d\n", *bp); - result = 1; - } - - return result; -} - - -#include <support/test-driver.c> diff --git a/elf/tst-tls3.c b/elf/tst-tls3.c deleted file mode 100644 index 7e0abb4c58..0000000000 --- a/elf/tst-tls3.c +++ /dev/null @@ -1,67 +0,0 @@ -/* glibc test for TLS in ld.so. */ -#include <stdio.h> - -#include "tls-macros.h" - - -/* One define int variable, two externs. */ -COMMON_INT_DECL(foo); -VAR_INT_DECL(bar); -VAR_INT_DEF(baz); - - -extern int in_dso (void); - - -static int -do_test (void) -{ - int result = 0; - int *ap, *bp, *cp; - - - /* Set the variable using the local exec model. */ - puts ("set baz to 3 (LE)"); - ap = TLS_LE (baz); - *ap = 3; - - - /* Get variables using initial exec model. */ - puts ("set variables foo and bar (IE)"); - ap = TLS_IE (foo); - *ap = 1; - bp = TLS_IE (bar); - *bp = 2; - - - /* Get variables using local dynamic model. */ - fputs ("get sum of foo, bar (GD) and baz (LD)", stdout); - ap = TLS_GD (foo); - bp = TLS_GD (bar); - cp = TLS_LD (baz); - printf (" = %d\n", *ap + *bp + *cp); - result |= *ap + *bp + *cp != 6; - if (*ap != 1) - { - printf ("foo = %d\n", *ap); - result = 1; - } - if (*bp != 2) - { - printf ("bar = %d\n", *bp); - result = 1; - } - if (*cp != 3) - { - printf ("baz = %d\n", *cp); - result = 1; - } - - - result |= in_dso (); - - return result; -} - - -#include <support/test-driver.c> diff --git a/elf/tst-tls4.c b/elf/tst-tls4.c deleted file mode 100644 index 6841f81386..0000000000 --- a/elf/tst-tls4.c +++ /dev/null @@ -1,49 +0,0 @@ -#include <dlfcn.h> -#include <stdio.h> -#include <stdlib.h> - - -static int -do_test (void) -{ - static const char modname[] = "tst-tlsmod2.so"; - int result = 0; - int *foop; - int (*fp) (int, int *); - void *h; - - h = dlopen (modname, RTLD_LAZY); - if (h == NULL) - { - printf ("cannot open '%s': %s\n", modname, dlerror ()); - exit (1); - } - - fp = dlsym (h, "in_dso"); - if (fp == NULL) - { - printf ("cannot get symbol 'in_dso': %s\n", dlerror ()); - exit (1); - } - - result |= fp (0, NULL); - - foop = dlsym (h, "foo"); - if (foop == NULL) - { - printf ("cannot get symbol 'foo' the second time: %s\n", dlerror ()); - exit (1); - } - if (*foop != 16) - { - puts ("foo != 16"); - result = 1; - } - - dlclose (h); - - return result; -} - - -#include <support/test-driver.c> diff --git a/elf/tst-tls5.c b/elf/tst-tls5.c deleted file mode 100644 index 5f006fd645..0000000000 --- a/elf/tst-tls5.c +++ /dev/null @@ -1,65 +0,0 @@ -#include <dlfcn.h> -#include <stdio.h> -#include <stdlib.h> - - -static int -do_test (void) -{ - static const char modname[] = "tst-tlsmod2.so"; - int result = 0; - int *foop; - int *foop2; - int (*fp) (int, int *); - void *h; - - h = dlopen (modname, RTLD_LAZY); - if (h == NULL) - { - printf ("cannot open '%s': %s\n", modname, dlerror ()); - exit (1); - } - - foop = dlsym (h, "foo"); - if (foop == NULL) - { - printf ("cannot get symbol 'foo': %s\n", dlerror ()); - exit (1); - } - - *foop = 42; - - fp = dlsym (h, "in_dso"); - if (fp == NULL) - { - printf ("cannot get symbol 'in_dso': %s\n", dlerror ()); - exit (1); - } - - result |= fp (42, foop); - - foop2 = dlsym (h, "foo"); - if (foop2 == NULL) - { - printf ("cannot get symbol 'foo' the second time: %s\n", dlerror ()); - exit (1); - } - - if (foop != foop2) - { - puts ("address of 'foo' different the second time"); - result = 1; - } - else if (*foop != 16) - { - puts ("foo != 16"); - result = 1; - } - - dlclose (h); - - return result; -} - - -#include <support/test-driver.c> diff --git a/elf/tst-tls6.c b/elf/tst-tls6.c deleted file mode 100644 index df81c1f6b4..0000000000 --- a/elf/tst-tls6.c +++ /dev/null @@ -1,84 +0,0 @@ -#include <dlfcn.h> -#include <stdio.h> -#include <stdlib.h> - -#include <link.h> - - -static int -do_test (void) -{ - static const char modname[] = "tst-tlsmod2.so"; - int result = 0; - int *foop; - int *foop2; - int (*fp) (int, int *); - void *h; - int i; - int modid = -1; - - for (i = 0; i < 10; ++i) - { - h = dlopen (modname, RTLD_LAZY); - if (h == NULL) - { - printf ("cannot open '%s': %s\n", modname, dlerror ()); - exit (1); - } - - /* Dirty test code here: we peek into a private data structure. - We make sure that the module gets assigned the same ID every - time. The value of the first round is used. */ - if (modid == -1) - modid = ((struct link_map *) h)->l_tls_modid; - else if (((struct link_map *) h)->l_tls_modid != modid) - { - printf ("round %d: modid now %zd, initially %d\n", - i, ((struct link_map *) h)->l_tls_modid, modid); - result = 1; - } - - foop = dlsym (h, "foo"); - if (foop == NULL) - { - printf ("cannot get symbol 'foo': %s\n", dlerror ()); - exit (1); - } - - *foop = 42 + i; - - fp = dlsym (h, "in_dso"); - if (fp == NULL) - { - printf ("cannot get symbol 'in_dso': %s\n", dlerror ()); - exit (1); - } - - result |= fp (42 + i, foop); - - foop2 = dlsym (h, "foo"); - if (foop2 == NULL) - { - printf ("cannot get symbol 'foo' the second time: %s\n", dlerror ()); - exit (1); - } - - if (foop != foop2) - { - puts ("address of 'foo' different the second time"); - result = 1; - } - else if (*foop != 16) - { - puts ("foo != 16"); - result = 1; - } - - dlclose (h); - } - - return result; -} - - -#include <support/test-driver.c> diff --git a/elf/tst-tls7.c b/elf/tst-tls7.c deleted file mode 100644 index fa46709600..0000000000 --- a/elf/tst-tls7.c +++ /dev/null @@ -1,55 +0,0 @@ -#include <dlfcn.h> -#include <stdio.h> -#include <stdlib.h> - -#include <link.h> - - -static int -do_test (void) -{ - static const char modname[] = "tst-tlsmod3.so"; - int result = 0; - int (*fp) (void); - void *h; - int i; - int modid = -1; - - for (i = 0; i < 10; ++i) - { - h = dlopen (modname, RTLD_LAZY); - if (h == NULL) - { - printf ("cannot open '%s': %s\n", modname, dlerror ()); - exit (1); - } - - /* Dirty test code here: we peek into a private data structure. - We make sure that the module gets assigned the same ID every - time. The value of the first round is used. */ - if (modid == -1) - modid = ((struct link_map *) h)->l_tls_modid; - else if (((struct link_map *) h)->l_tls_modid != (size_t) modid) - { - printf ("round %d: modid now %zu, initially %d\n", - i, ((struct link_map *) h)->l_tls_modid, modid); - result = 1; - } - - fp = dlsym (h, "in_dso2"); - if (fp == NULL) - { - printf ("cannot get symbol 'in_dso2': %s\n", dlerror ()); - exit (1); - } - - result |= fp (); - - dlclose (h); - } - - return result; -} - - -#include <support/test-driver.c> diff --git a/elf/tst-tls8.c b/elf/tst-tls8.c deleted file mode 100644 index c779572617..0000000000 --- a/elf/tst-tls8.c +++ /dev/null @@ -1,167 +0,0 @@ -#include <dlfcn.h> -#include <stdio.h> -#include <stdlib.h> - -#include <link.h> - - -static int -do_test (void) -{ - static const char modname1[] = "$ORIGIN/tst-tlsmod3.so"; - static const char modname2[] = "$ORIGIN/tst-tlsmod4.so"; - int result = 0; - int (*fp1) (void); - int (*fp2) (int, int *); - void *h1; - void *h2; - int i; - size_t modid1 = (size_t) -1; - size_t modid2 = (size_t) -1; - int *bazp; - - for (i = 0; i < 10; ++i) - { - h1 = dlopen (modname1, RTLD_LAZY); - if (h1 == NULL) - { - printf ("cannot open '%s': %s\n", modname1, dlerror ()); - exit (1); - } - - /* Dirty test code here: we peek into a private data structure. - We make sure that the module gets assigned the same ID every - time. The value of the first round is used. */ - if (modid1 == (size_t) -1) - modid1 = ((struct link_map *) h1)->l_tls_modid; - else if (((struct link_map *) h1)->l_tls_modid != modid1) - { - printf ("round %d: modid now %zd, initially %zd\n", - i, ((struct link_map *) h1)->l_tls_modid, modid1); - result = 1; - } - - fp1 = dlsym (h1, "in_dso2"); - if (fp1 == NULL) - { - printf ("cannot get symbol 'in_dso2' in %s\n", modname1); - exit (1); - } - - result |= fp1 (); - - - - h2 = dlopen (modname2, RTLD_LAZY); - if (h2 == NULL) - { - printf ("cannot open '%s': %s\n", modname2, dlerror ()); - exit (1); - } - - /* Dirty test code here: we peek into a private data structure. - We make sure that the module gets assigned the same ID every - time. The value of the first round is used. */ - if (modid2 == (size_t) -1) - modid2 = ((struct link_map *) h1)->l_tls_modid; - else if (((struct link_map *) h1)->l_tls_modid != modid2) - { - printf ("round %d: modid now %zd, initially %zd\n", - i, ((struct link_map *) h1)->l_tls_modid, modid2); - result = 1; - } - - bazp = dlsym (h2, "baz"); - if (bazp == NULL) - { - printf ("cannot get symbol 'baz' in %s\n", modname2); - exit (1); - } - - *bazp = 42 + i; - - fp2 = dlsym (h2, "in_dso"); - if (fp2 == NULL) - { - printf ("cannot get symbol 'in_dso' in %s\n", modname2); - exit (1); - } - - result |= fp2 (42 + i, bazp); - - dlclose (h1); - dlclose (h2); - - - h1 = dlopen (modname1, RTLD_LAZY); - if (h1 == NULL) - { - printf ("cannot open '%s': %s\n", modname1, dlerror ()); - exit (1); - } - - /* Dirty test code here: we peek into a private data structure. - We make sure that the module gets assigned the same ID every - time. The value of the first round is used. */ - if (((struct link_map *) h1)->l_tls_modid != modid1) - { - printf ("round %d: modid now %zd, initially %zd\n", - i, ((struct link_map *) h1)->l_tls_modid, modid1); - result = 1; - } - - fp1 = dlsym (h1, "in_dso2"); - if (fp1 == NULL) - { - printf ("cannot get symbol 'in_dso2' in %s\n", modname1); - exit (1); - } - - result |= fp1 (); - - - - h2 = dlopen (modname2, RTLD_LAZY); - if (h2 == NULL) - { - printf ("cannot open '%s': %s\n", modname2, dlerror ()); - exit (1); - } - - /* Dirty test code here: we peek into a private data structure. - We make sure that the module gets assigned the same ID every - time. The value of the first round is used. */ - if (((struct link_map *) h1)->l_tls_modid != modid2) - { - printf ("round %d: modid now %zd, initially %zd\n", - i, ((struct link_map *) h1)->l_tls_modid, modid2); - result = 1; - } - - bazp = dlsym (h2, "baz"); - if (bazp == NULL) - { - printf ("cannot get symbol 'baz' in %s\n", modname2); - exit (1); - } - - *bazp = 62 + i; - - fp2 = dlsym (h2, "in_dso"); - if (fp2 == NULL) - { - printf ("cannot get symbol 'in_dso' in %s\n", modname2); - exit (1); - } - - result |= fp2 (62 + i, bazp); - - /* This time the dlclose calls are in reverse order. */ - dlclose (h2); - dlclose (h1); - } - - return result; -} - -#include <support/test-driver.c> diff --git a/elf/tst-tls9-static.c b/elf/tst-tls9-static.c deleted file mode 100644 index 51812ccc7d..0000000000 --- a/elf/tst-tls9-static.c +++ /dev/null @@ -1 +0,0 @@ -#include "tst-tls9.c" diff --git a/elf/tst-tls9.c b/elf/tst-tls9.c deleted file mode 100644 index ee21b47c70..0000000000 --- a/elf/tst-tls9.c +++ /dev/null @@ -1,36 +0,0 @@ -#include <dlfcn.h> -#include <stdio.h> -#include <stdlib.h> - -#include <link.h> - -static int -do_test (void) -{ - static const char modname1[] = "tst-tlsmod5.so"; - static const char modname2[] = "tst-tlsmod6.so"; - int result = 0; - - void *h1 = dlopen (modname1, RTLD_LAZY); - if (h1 == NULL) - { - printf ("cannot open '%s': %s\n", modname1, dlerror ()); - result = 1; - } - void *h2 = dlopen (modname2, RTLD_LAZY); - if (h2 == NULL) - { - printf ("cannot open '%s': %s\n", modname2, dlerror ()); - result = 1; - } - - if (h1 != NULL) - dlclose (h1); - if (h2 != NULL) - dlclose (h2); - - return result; -} - - -#include <support/test-driver.c> diff --git a/elf/tst-tlsalign-extern-static.c b/elf/tst-tlsalign-extern-static.c deleted file mode 100644 index e84900eee4..0000000000 --- a/elf/tst-tlsalign-extern-static.c +++ /dev/null @@ -1 +0,0 @@ -#include "tst-tlsalign-extern.c" diff --git a/elf/tst-tlsalign-extern.c b/elf/tst-tlsalign-extern.c deleted file mode 100644 index 11384d085e..0000000000 --- a/elf/tst-tlsalign-extern.c +++ /dev/null @@ -1,73 +0,0 @@ -/* Test for large alignment in TLS blocks (extern case), BZ#18383. - Copyright (C) 2015-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -#include <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; -} - -#include <support/test-driver.c> diff --git a/elf/tst-tlsalign-lib.c b/elf/tst-tlsalign-lib.c deleted file mode 100644 index 4371e581a6..0000000000 --- a/elf/tst-tlsalign-lib.c +++ /dev/null @@ -1,6 +0,0 @@ -__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 deleted file mode 100644 index 1671abf28e..0000000000 --- a/elf/tst-tlsalign-static.c +++ /dev/null @@ -1,2 +0,0 @@ -#define NO_LIB -#include "tst-tlsalign.c" diff --git a/elf/tst-tlsalign-vars.c b/elf/tst-tlsalign-vars.c deleted file mode 100644 index 01b3501d3b..0000000000 --- a/elf/tst-tlsalign-vars.c +++ /dev/null @@ -1,28 +0,0 @@ -/* 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 deleted file mode 100644 index b129ebda0e..0000000000 --- a/elf/tst-tlsalign.c +++ /dev/null @@ -1,84 +0,0 @@ -/* Test for large alignment in TLS blocks, BZ#18383. - Copyright (C) 2015-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -#include <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; -} - -#include <support/test-driver.c> diff --git a/elf/tst-tlsmod1.c b/elf/tst-tlsmod1.c deleted file mode 100644 index 8d9156791b..0000000000 --- a/elf/tst-tlsmod1.c +++ /dev/null @@ -1,62 +0,0 @@ -#include <stdio.h> - -#include "tls-macros.h" - - -/* One define int variable, two externs. */ -COMMON_INT_DEF(foo); -VAR_INT_DEF(bar); -VAR_INT_DECL(baz); - -extern int in_dso (void); - -int -in_dso (void) -{ - int result = 0; - int *ap, *bp, *cp; - - /* Get variables using initial exec model. */ - fputs ("get sum of foo and bar (IE)", stdout); - asm ("" ::: "memory"); - ap = TLS_IE (foo); - bp = TLS_IE (bar); - printf (" = %d\n", *ap + *bp); - result |= *ap + *bp != 3; - if (*ap != 1) - { - printf ("foo = %d\n", *ap); - result = 1; - } - if (*bp != 2) - { - printf ("bar = %d\n", *bp); - result = 1; - } - - - /* Get variables using generic dynamic model. */ - fputs ("get sum of foo and bar and baz (GD)", stdout); - ap = TLS_GD (foo); - bp = TLS_GD (bar); - cp = TLS_GD (baz); - printf (" = %d\n", *ap + *bp + *cp); - result |= *ap + *bp + *cp != 6; - if (*ap != 1) - { - printf ("foo = %d\n", *ap); - result = 1; - } - if (*bp != 2) - { - printf ("bar = %d\n", *bp); - result = 1; - } - if (*cp != 3) - { - printf ("baz = %d\n", *cp); - result = 1; - } - - return result; -} diff --git a/elf/tst-tlsmod10.c b/elf/tst-tlsmod10.c deleted file mode 100644 index 32e54f3c04..0000000000 --- a/elf/tst-tlsmod10.c +++ /dev/null @@ -1 +0,0 @@ -#include "tst-tlsmod8.c" diff --git a/elf/tst-tlsmod11.c b/elf/tst-tlsmod11.c deleted file mode 100644 index cffbd68edc..0000000000 --- a/elf/tst-tlsmod11.c +++ /dev/null @@ -1,4 +0,0 @@ -#include "tst-tls10.h" - -__thread struct A a1 = { 4, 5, 6 }; -__thread struct A a2 = { 7, 8, 9 }; diff --git a/elf/tst-tlsmod12.c b/elf/tst-tlsmod12.c deleted file mode 100644 index d0be51891a..0000000000 --- a/elf/tst-tlsmod12.c +++ /dev/null @@ -1,12 +0,0 @@ -#include "tst-tls10.h" - -extern __thread struct A a2 __attribute__((tls_model("initial-exec"))); - -void -check1 (void) -{ - if (a1.a != 4 || a1.b != 5 || a1.c != 6) - abort (); - if (a2.a != 7 || a2.b != 8 || a2.c != 9) - abort (); -} diff --git a/elf/tst-tlsmod13.c b/elf/tst-tlsmod13.c deleted file mode 100644 index 7712d8b8c8..0000000000 --- a/elf/tst-tlsmod13.c +++ /dev/null @@ -1,7 +0,0 @@ -__thread int a[2] __attribute__ ((tls_model ("initial-exec"))); - -int -foo (void) -{ - return a[0]; -} diff --git a/elf/tst-tlsmod13a.c b/elf/tst-tlsmod13a.c deleted file mode 100644 index ca4eaccbff..0000000000 --- a/elf/tst-tlsmod13a.c +++ /dev/null @@ -1,9 +0,0 @@ -__thread int b[2] __attribute__ ((tls_model ("initial-exec"))); - -extern int foo (void); - -int -bar (void) -{ - return foo () + b[0]; -} diff --git a/elf/tst-tlsmod14a.c b/elf/tst-tlsmod14a.c deleted file mode 100644 index 824c06d1f9..0000000000 --- a/elf/tst-tlsmod14a.c +++ /dev/null @@ -1,35 +0,0 @@ -#include <stdint.h> -#include <stdio.h> - -#define AL 4096 -struct foo -{ - int i; -} __attribute ((aligned (AL))); - -static __thread struct foo f; -static struct foo g; - - -#ifndef FCT -# define FCT in_dso1 -#endif - - -int -FCT (void) -{ - puts (__func__); - - int result = 0; - - int fail = (((uintptr_t) &f) & (AL - 1)) != 0; - printf ("&f = %p %s\n", &f, fail ? "FAIL" : "OK"); - result |= fail; - - fail = (((uintptr_t) &g) & (AL - 1)) != 0; - printf ("&g = %p %s\n", &g, fail ? "FAIL" : "OK"); - result |= fail; - - return result; -} diff --git a/elf/tst-tlsmod14b.c b/elf/tst-tlsmod14b.c deleted file mode 100644 index 24d9ceaf7e..0000000000 --- a/elf/tst-tlsmod14b.c +++ /dev/null @@ -1,2 +0,0 @@ -#define FCT in_dso2 -#include "tst-tlsmod14a.c" diff --git a/elf/tst-tlsmod15a.c b/elf/tst-tlsmod15a.c deleted file mode 100644 index 66c707129a..0000000000 --- a/elf/tst-tlsmod15a.c +++ /dev/null @@ -1,6 +0,0 @@ -extern int nonexistent_dummy_var; -int * -foo (void) -{ - return &nonexistent_dummy_var; -} diff --git a/elf/tst-tlsmod15b.c b/elf/tst-tlsmod15b.c deleted file mode 100644 index b37283686a..0000000000 --- a/elf/tst-tlsmod15b.c +++ /dev/null @@ -1,9 +0,0 @@ -#include "tst-tls10.h" - -__thread int mod15b_var __attribute__((tls_model("initial-exec"))); - -int -in_dso (void) -{ - return mod15b_var; -} diff --git a/elf/tst-tlsmod16a.c b/elf/tst-tlsmod16a.c deleted file mode 100644 index 4ec6a6c37d..0000000000 --- a/elf/tst-tlsmod16a.c +++ /dev/null @@ -1 +0,0 @@ -int __thread tlsvar; diff --git a/elf/tst-tlsmod16b.c b/elf/tst-tlsmod16b.c deleted file mode 100644 index 1ecba26dbe..0000000000 --- a/elf/tst-tlsmod16b.c +++ /dev/null @@ -1,7 +0,0 @@ -extern __thread int tlsvar __attribute__((tls_model("initial-exec"))); - -void * -in_dso (void) -{ - return &tlsvar; -} diff --git a/elf/tst-tlsmod17a.c b/elf/tst-tlsmod17a.c deleted file mode 100644 index 24c84a1590..0000000000 --- a/elf/tst-tlsmod17a.c +++ /dev/null @@ -1,23 +0,0 @@ -#include <stdio.h> - -#ifndef N -#define N 0 -#endif -#define CONCAT1(s, n) s##n -#define CONCAT(s, n) CONCAT1(s, n) - -__thread int CONCAT (v, N) = 4; - -int -CONCAT (tlsmod17a, N) (void) -{ - int *p = &CONCAT (v, N); - /* GCC assumes &var is never NULL, add optimization barrier. */ - asm volatile ("" : "+r" (p)); - if (p == NULL || *p != 4) - { - printf ("fail %d %p\n", N, p); - return 1; - } - return 0; -} diff --git a/elf/tst-tlsmod17b.c b/elf/tst-tlsmod17b.c deleted file mode 100644 index 6178828737..0000000000 --- a/elf/tst-tlsmod17b.c +++ /dev/null @@ -1,15 +0,0 @@ -#define P(N) extern int tlsmod17a##N (void); -#define PS P(0) P(1) P(2) P(3) P(4) P(5) P(6) P(7) P(8) P(9) \ - P(10) P(12) P(13) P(14) P(15) P(16) P(17) P(18) P(19) -PS -#undef P - -int -tlsmod17b (void) -{ - int res = 0; -#define P(N) res |= tlsmod17a##N (); - PS -#undef P - return res; -} diff --git a/elf/tst-tlsmod18a.c b/elf/tst-tlsmod18a.c deleted file mode 100644 index 1d728daa05..0000000000 --- a/elf/tst-tlsmod18a.c +++ /dev/null @@ -1,21 +0,0 @@ -#include <stdio.h> - -#ifndef N -# define N 0 -#endif - -static __thread int var = 4; - -int -test (void) -{ - int *p = &var; - /* GCC assumes &var is never NULL, add optimization barrier. */ - asm volatile ("" : "+r" (p)); - if (p == NULL || *p != 4) - { - printf ("fail %d %p\n", N, p); - return 1; - } - return 0; -} diff --git a/elf/tst-tlsmod2.c b/elf/tst-tlsmod2.c deleted file mode 100644 index 40eb1407f8..0000000000 --- a/elf/tst-tlsmod2.c +++ /dev/null @@ -1,34 +0,0 @@ -#include <stdio.h> - -#include "tls-macros.h" - - -COMMON_INT_DEF(foo); - - -int -in_dso (int n, int *caller_foop) -{ - int *foop; - int result = 0; - - puts ("foo"); /* Make sure PLT is used before macros. */ - asm ("" ::: "memory"); - - foop = TLS_GD (foo); - - if (caller_foop != NULL && foop != caller_foop) - { - printf ("callers address of foo differs: %p vs %p\n", caller_foop, foop); - result = 1; - } - else if (*foop != n) - { - printf ("foo != %d\n", n); - result = 1; - } - - *foop = 16; - - return result; -} diff --git a/elf/tst-tlsmod3.c b/elf/tst-tlsmod3.c deleted file mode 100644 index 6d186c47ee..0000000000 --- a/elf/tst-tlsmod3.c +++ /dev/null @@ -1,37 +0,0 @@ -#include <stdio.h> - -#include "tls-macros.h" - -extern int in_dso (int n, int *caller_foop); - -COMMON_INT_DEF(comm_n); - - - - -int -in_dso2 (void) -{ - int *foop; - int result = 0; - static int n; - int *np; - - puts ("foo"); /* Make sure PLT is used before macros. */ - asm ("" ::: "memory"); - - foop = TLS_GD (foo); - np = TLS_GD (comm_n); - - if (n != *np) - { - printf ("n = %d != comm_n = %d\n", n, *np); - result = 1; - } - - result |= in_dso (*foop = 42 + n++, foop); - - *foop = 16; - - return result; -} diff --git a/elf/tst-tlsmod4.c b/elf/tst-tlsmod4.c deleted file mode 100644 index 86889aac7e..0000000000 --- a/elf/tst-tlsmod4.c +++ /dev/null @@ -1,34 +0,0 @@ -#include <stdio.h> - -#include "tls-macros.h" - - -COMMON_INT_DEF(baz); - - -int -in_dso (int n, int *caller_bazp) -{ - int *bazp; - int result = 0; - - puts ("foo"); /* Make sure PLT is used before macros. */ - asm ("" ::: "memory"); - - bazp = TLS_GD (baz); - - if (caller_bazp != NULL && bazp != caller_bazp) - { - printf ("callers address of baz differs: %p vs %p\n", caller_bazp, bazp); - result = 1; - } - else if (*bazp != n) - { - printf ("baz != %d\n", n); - result = 1; - } - - *bazp = 16; - - return result; -} diff --git a/elf/tst-tlsmod5.c b/elf/tst-tlsmod5.c deleted file mode 100644 index a97c7e5e0c..0000000000 --- a/elf/tst-tlsmod5.c +++ /dev/null @@ -1,3 +0,0 @@ -#include "tls-macros.h" - -COMMON_INT_DEF(foo); diff --git a/elf/tst-tlsmod6.c b/elf/tst-tlsmod6.c deleted file mode 100644 index e968596dd4..0000000000 --- a/elf/tst-tlsmod6.c +++ /dev/null @@ -1,3 +0,0 @@ -#include "tls-macros.h" - -COMMON_INT_DEF(bar); diff --git a/elf/tst-tlsmod7.c b/elf/tst-tlsmod7.c deleted file mode 100644 index 3df7907bcf..0000000000 --- a/elf/tst-tlsmod7.c +++ /dev/null @@ -1,101 +0,0 @@ -#include "tst-tls10.h" - -__thread int dummy __attribute__((visibility ("hidden"))) = 12; -__thread struct A a1 = { 4, 5, 6 }; -__thread struct A a2 = { 7, 8, 9 }; -__thread struct A a3 __attribute__((tls_model("initial-exec"))) - = { 10, 11, 12 }; -__thread struct A a4 __attribute__((tls_model("initial-exec"))) - = { 13, 14, 15 }; -static __thread struct A local1 = { 16, 17, 18 }; -static __thread struct A local2 __attribute__((tls_model("initial-exec"))) - = { 19, 20, 21 }; - -void -check1 (void) -{ - if (a1.a != 4 || a1.b != 5 || a1.c != 6) - abort (); - if (a2.a != 22 || a2.b != 23 || a2.c != 24) - abort (); - if (a3.a != 10 || a3.b != 11 || a3.c != 12) - abort (); - if (a4.a != 25 || a4.b != 26 || a4.c != 27) - abort (); - if (local1.a != 16 || local1.b != 17 || local1.c != 18) - abort (); - if (local2.a != 19 || local2.b != 20 || local2.c != 21) - abort (); -} - -struct A * -f1a (void) -{ - return &a1; -} - -struct A * -f2a (void) -{ - return &a2; -} - -struct A * -f3a (void) -{ - return &a3; -} - -struct A * -f4a (void) -{ - return &a4; -} - -struct A * -f5a (void) -{ - return &local1; -} - -struct A * -f6a (void) -{ - return &local2; -} - -int -f1b (void) -{ - return a1.a; -} - -int -f2b (void) -{ - return a2.b; -} - -int -f3b (void) -{ - return a3.c; -} - -int -f4b (void) -{ - return a4.a; -} - -int -f5b (void) -{ - return local1.b; -} - -int -f6b (void) -{ - return local2.c; -} diff --git a/elf/tst-tlsmod8.c b/elf/tst-tlsmod8.c deleted file mode 100644 index 89772ac42f..0000000000 --- a/elf/tst-tlsmod8.c +++ /dev/null @@ -1,70 +0,0 @@ -#include "tst-tls10.h" - -__thread long long dummy __attribute__((visibility ("hidden"))) = 12; -__thread struct A a2 = { 22, 23, 24 }; -__thread struct A a4 __attribute__((tls_model("initial-exec"))) - = { 25, 26, 27 }; -static __thread struct A local1 = { 28, 29, 30 }; -static __thread struct A local2 __attribute__((tls_model("initial-exec"))) - = { 31, 32, 33 }; - -void -check2 (void) -{ - if (a2.a != 22 || a2.b != 23 || a2.c != 24) - abort (); - if (a4.a != 25 || a4.b != 26 || a4.c != 27) - abort (); - if (local1.a != 28 || local1.b != 29 || local1.c != 30) - abort (); - if (local2.a != 31 || local2.b != 32 || local2.c != 33) - abort (); -} - -struct A * -f7a (void) -{ - return &a2; -} - -struct A * -f8a (void) -{ - return &a4; -} - -struct A * -f9a (void) -{ - return &local1; -} - -struct A * -f10a (void) -{ - return &local2; -} - -int -f7b (void) -{ - return a2.b; -} - -int -f8b (void) -{ - return a4.a; -} - -int -f9b (void) -{ - return local1.b; -} - -int -f10b (void) -{ - return local2.c; -} diff --git a/elf/tst-tlsmod9.c b/elf/tst-tlsmod9.c deleted file mode 100644 index 6b11ed58b8..0000000000 --- a/elf/tst-tlsmod9.c +++ /dev/null @@ -1,99 +0,0 @@ -#include "tst-tls10.h" - -__thread int dummy __attribute__((visibility ("hidden"))) = 12; -__thread struct A a1 = { 4, 5, 6 }; -__thread struct A a3 __attribute__((tls_model("initial-exec"))) - = { 10, 11, 12 }; -extern __thread struct A a4 __attribute__((tls_model("initial-exec"))); -static __thread struct A local1 = { 16, 17, 18 }; -static __thread struct A local2 __attribute__((tls_model("initial-exec"))) - = { 19, 20, 21 }; - -void -check1 (void) -{ - if (a1.a != 4 || a1.b != 5 || a1.c != 6) - abort (); - if (a2.a != 22 || a2.b != 23 || a2.c != 24) - abort (); - if (a3.a != 10 || a3.b != 11 || a3.c != 12) - abort (); - if (a4.a != 25 || a4.b != 26 || a4.c != 27) - abort (); - if (local1.a != 16 || local1.b != 17 || local1.c != 18) - abort (); - if (local2.a != 19 || local2.b != 20 || local2.c != 21) - abort (); -} - -struct A * -f1a (void) -{ - return &a1; -} - -struct A * -f2a (void) -{ - return &a2; -} - -struct A * -f3a (void) -{ - return &a3; -} - -struct A * -f4a (void) -{ - return &a4; -} - -struct A * -f5a (void) -{ - return &local1; -} - -struct A * -f6a (void) -{ - return &local2; -} - -int -f1b (void) -{ - return a1.a; -} - -int -f2b (void) -{ - return a2.b; -} - -int -f3b (void) -{ - return a3.c; -} - -int -f4b (void) -{ - return a4.a; -} - -int -f5b (void) -{ - return local1.b; -} - -int -f6b (void) -{ - return local2.c; -} diff --git a/elf/tst-unique1.c b/elf/tst-unique1.c deleted file mode 100644 index b5e53e49a0..0000000000 --- a/elf/tst-unique1.c +++ /dev/null @@ -1,73 +0,0 @@ -#include <config.h> -#include <dlfcn.h> -#include <stdio.h> -#include <sys/mman.h> - -static int -do_test (void) -{ - void *h1 = dlopen ("tst-unique1mod1.so", RTLD_LAZY); - if (h1 == NULL) - { - puts ("cannot load tst-unique1mod1"); - return 1; - } - int *(*f1) (void) = dlsym (h1, "f"); - if (f1 == NULL) - { - puts ("cannot locate f in tst-unique1mod1"); - return 1; - } - void *h2 = dlopen ("tst-unique1mod2.so", RTLD_LAZY); - if (h2 == NULL) - { - puts ("cannot load tst-unique1mod2"); - return 1; - } - int (*f2) (int *) = dlsym (h2, "f"); - if (f2 == NULL) - { - puts ("cannot locate f in tst-unique1mod2"); - return 1; - } - if (f2 (f1 ())) - { - puts ("f from tst-unique1mod2 failed"); - return 1; - } - dlclose (h2); - dlclose (h1); - mmap (NULL, 1024 * 1024 * 16, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); - h2 = dlopen ("tst-unique1mod2.so", RTLD_LAZY); - if (h2 == NULL) - { - puts ("cannot load tst-unique1mod2"); - return 1; - } - f2 = dlsym (h2, "f"); - if (f2 == NULL) - { - puts ("cannot locate f in tst-unique1mod2"); - return 1; - } - h1 = dlopen ("tst-unique1mod1.so", RTLD_LAZY); - if (h1 == NULL) - { - puts ("cannot load tst-unique1mod1"); - return 1; - } - f1 = dlsym (h1, "f"); - if (f1 == NULL) - { - puts ("cannot locate f in tst-unique1mod1"); - return 1; - } - if (f2 (f1 ())) - { - puts ("f from tst-unique1mod2 failed"); - return 1; - } - return 0; -} - -#include <support/test-driver.c> diff --git a/elf/tst-unique1mod1.c b/elf/tst-unique1mod1.c deleted file mode 100644 index 84b1f908d6..0000000000 --- a/elf/tst-unique1mod1.c +++ /dev/null @@ -1,16 +0,0 @@ -#include <config.h> - -asm (".data;" - ".globl var\n" - ".type var, %gnu_unique_object\n" - ".size var, 4\n" - "var:.zero 4\n" - ".previous"); -extern int var; - -int * -f (void) -{ - var = 1; - return &var; -} diff --git a/elf/tst-unique1mod2.c b/elf/tst-unique1mod2.c deleted file mode 100644 index 126ca1ac6c..0000000000 --- a/elf/tst-unique1mod2.c +++ /dev/null @@ -1,15 +0,0 @@ -#include <config.h> - -asm (".data;" - ".globl var\n" - ".type var, %gnu_unique_object\n" - ".size var, 4\n" - "var:.zero 4\n" - ".previous"); -extern int var; - -int -f (int *p) -{ - return &var != p || *p != 1; -} diff --git a/elf/tst-unique2.c b/elf/tst-unique2.c deleted file mode 100644 index e0173b7bcc..0000000000 --- a/elf/tst-unique2.c +++ /dev/null @@ -1,27 +0,0 @@ -#include <config.h> -#include <dlfcn.h> -#include <stdio.h> - -extern int var; - -static int -do_test (void) -{ - var = 1; - - void *h = dlopen ("tst-unique2mod2.so", RTLD_LAZY); - if (h == NULL) - { - puts ("cannot load tst-unique2mod2"); - return 1; - } - int (*f) (int *) = dlsym (h, "f"); - if (f == NULL) - { - puts ("cannot locate f in tst-unique2mod2"); - return 1; - } - return f (&var); -} - -#include <support/test-driver.c> diff --git a/elf/tst-unique2mod1.c b/elf/tst-unique2mod1.c deleted file mode 100644 index 7cdb0eb0a0..0000000000 --- a/elf/tst-unique2mod1.c +++ /dev/null @@ -1,8 +0,0 @@ -#include <config.h> - -asm (".data;" - ".globl var\n" - ".type var, %gnu_unique_object\n" - ".size var, 4\n" - "var:.zero 4\n" - ".previous"); diff --git a/elf/tst-unique2mod2.c b/elf/tst-unique2mod2.c deleted file mode 100644 index 126ca1ac6c..0000000000 --- a/elf/tst-unique2mod2.c +++ /dev/null @@ -1,15 +0,0 @@ -#include <config.h> - -asm (".data;" - ".globl var\n" - ".type var, %gnu_unique_object\n" - ".size var, 4\n" - "var:.zero 4\n" - ".previous"); -extern int var; - -int -f (int *p) -{ - return &var != p || *p != 1; -} diff --git a/elf/tst-unique3.cc b/elf/tst-unique3.cc deleted file mode 100644 index efdd6d78c2..0000000000 --- a/elf/tst-unique3.cc +++ /dev/null @@ -1,24 +0,0 @@ -#include "tst-unique3.h" - -#include <cstdio> -#include "../dlfcn/dlfcn.h" - -int t = S<char>::i; - -int -main (void) -{ - std::printf ("%d %d\n", S<char>::i, t); - int result = S<char>::i++ != 1 || t != 1; - result |= in_lib (); - void *d = dlopen ("$ORIGIN/tst-unique3lib2.so", RTLD_LAZY); - int (*fp) (); - if (d == NULL || (fp = (int(*)()) dlsym (d, "in_lib2")) == NULL) - { - std::printf ("failed to get symbol in_lib2\n"); - return 1; - } - result |= fp (); - dlclose (d); - return result; -} diff --git a/elf/tst-unique3.h b/elf/tst-unique3.h deleted file mode 100644 index 716d23641c..0000000000 --- a/elf/tst-unique3.h +++ /dev/null @@ -1,8 +0,0 @@ -// BZ 12510 -template<typename T> -struct S -{ - static int i; -}; - -extern int in_lib (void); diff --git a/elf/tst-unique3lib.cc b/elf/tst-unique3lib.cc deleted file mode 100644 index fa8e85a36c..0000000000 --- a/elf/tst-unique3lib.cc +++ /dev/null @@ -1,11 +0,0 @@ -#include <cstdio> -#include "tst-unique3.h" -template<typename T> int S<T>::i = 1; -static int i = S<char>::i; - -int -in_lib (void) -{ - std::printf ("in_lib: %d %d\n", S<char>::i, i); - return S<char>::i++ != 2 || i != 1; -} diff --git a/elf/tst-unique3lib2.cc b/elf/tst-unique3lib2.cc deleted file mode 100644 index 17d817e12e..0000000000 --- a/elf/tst-unique3lib2.cc +++ /dev/null @@ -1,12 +0,0 @@ -#include <cstdio> -#include "tst-unique3.h" - -template<typename T> int S<T>::i; - -extern "C" -int -in_lib2 () -{ - std::printf ("in_lib2: %d\n", S<char>::i); - return S<char>::i != 3; -} diff --git a/elf/tst-unique4.cc b/elf/tst-unique4.cc deleted file mode 100644 index 575c70d3a1..0000000000 --- a/elf/tst-unique4.cc +++ /dev/null @@ -1,28 +0,0 @@ -// BZ 12511 -#include "tst-unique4.h" - -#include <cstdio> - -static int a[24] = - { - 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, - S<16>::i, S<17>::i, S<18>::i, S<19>::i, S<20>::i, S<21>::i, S<22>::i, - S<23>::i, S<24>::i - }; - -int -main (void) -{ - int result = 0; - for (int i = 0; i < 24; ++i) - { - printf("%d ", a[i]); - result |= a[i] != i + 1; - } - - printf("\n%d\n", S<1>::j); - result |= S<1>::j != -1; - - return result; -} diff --git a/elf/tst-unique4.h b/elf/tst-unique4.h deleted file mode 100644 index 2d377f5d51..0000000000 --- a/elf/tst-unique4.h +++ /dev/null @@ -1,7 +0,0 @@ -// BZ 12511 -template<int N> -struct S -{ - static int i; - static const int j; -}; diff --git a/elf/tst-unique4lib.cc b/elf/tst-unique4lib.cc deleted file mode 100644 index 17a7cdf567..0000000000 --- a/elf/tst-unique4lib.cc +++ /dev/null @@ -1,17 +0,0 @@ -// BZ 12511 -#include "tst-unique4.h" - -template<int N> -int S<N>::i = N; -template<int N> -const int S<N>::j __attribute__ ((used)) = -1; - -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, - S<16>::i, S<17>::i, S<18>::i, S<19>::i, S<20>::i, S<21>::i, S<22>::i, - S<23>::i, S<24>::i - }; - -static int b __attribute__ ((used)) = S<1>::j; diff --git a/elf/unload.c b/elf/unload.c deleted file mode 100644 index 4566f226f8..0000000000 --- a/elf/unload.c +++ /dev/null @@ -1,91 +0,0 @@ -/* Test for unloading (really unmapping) of objects. By Franz Sirl. - This test does not have to passed in all dlopen() et.al. implementation - since it is not required the unloading actually happens. But we - require it for glibc. */ - -#include <dlfcn.h> -#include <link.h> -#include <mcheck.h> -#include <stdio.h> -#include <stdlib.h> - -#define MAPS ((struct link_map *) _r_debug.r_map) - -#define OUT \ - for (map = MAPS; map != NULL; map = map->l_next) \ - if (map->l_type == lt_loaded) \ - printf ("name = \"%s\", direct_opencount = %d\n", \ - map->l_name, (int) map->l_direct_opencount); \ - fflush (stdout) - -typedef struct -{ - void *next; -} strct; - -int -main (void) -{ - void *sohandle; - strct *testdat; - int ret; - int result = 0; - struct link_map *map; - - mtrace (); - - puts ("\nBefore"); - OUT; - - sohandle = dlopen ("unloadmod.so", RTLD_NOW | RTLD_GLOBAL); - if (sohandle == NULL) - { - printf ("*** first dlopen failed: %s\n", dlerror ()); - exit (1); - } - - puts ("\nAfter loading unloadmod.so"); - OUT; - - testdat = dlsym (sohandle, "testdat"); - testdat->next = (void *) -1; - - ret = dlclose (sohandle); - if (ret != 0) - { - puts ("*** first dlclose failed"); - result = 1; - } - - puts ("\nAfter closing unloadmod.so"); - OUT; - - sohandle = dlopen ("unloadmod.so", RTLD_NOW | RTLD_GLOBAL); - if (sohandle == NULL) - { - printf ("*** second dlopen failed: %s\n", dlerror ()); - exit (1); - } - - puts ("\nAfter loading unloadmod.so the second time"); - OUT; - - testdat = dlsym (sohandle, "testdat"); - if (testdat->next == (void *) -1) - { - puts ("*** testdat->next == (void *) -1"); - result = 1; - } - - ret = dlclose (sohandle); - if (ret != 0) - { - puts ("*** second dlclose failed"); - result = 1; - } - - puts ("\nAfter closing unloadmod.so again"); - OUT; - - return result; -} diff --git a/elf/unload2.c b/elf/unload2.c deleted file mode 100644 index eef2bfd426..0000000000 --- a/elf/unload2.c +++ /dev/null @@ -1,59 +0,0 @@ -#include <dlfcn.h> -#include <elf.h> -#include <errno.h> -#include <error.h> -#include <link.h> -#include <stdio.h> -#include <stdlib.h> - -#define MAPS ((struct link_map *) _r_debug.r_map) - -#define OUT \ - for (map = MAPS; map != NULL; map = map->l_next) \ - if (map->l_type == lt_loaded) \ - printf ("name = \"%s\", direct_opencount = %d\n", \ - map->l_name, (int) map->l_direct_opencount); \ - fflush (stdout) - -int -main (void) -{ - void *h[3]; - struct link_map *map; - void (*fp) (void); - - h[0] = dlopen ("unload2mod.so", RTLD_LAZY); - h[1] = dlopen ("unload2mod.so", RTLD_LAZY); - if (h[0] == NULL || h[1] == NULL) - error (EXIT_FAILURE, errno, "cannot load \"unload2mod.so\""); - h[2] = dlopen ("unload2dep.so", RTLD_LAZY); - if (h[2] == NULL) - error (EXIT_FAILURE, errno, "cannot load \"unload2dep.so\""); - - puts ("\nAfter loading everything:"); - OUT; - - dlclose (h[0]); - - puts ("\nAfter unloading \"unload2mod.so\" once:"); - OUT; - - dlclose (h[1]); - - puts ("\nAfter unloading \"unload2mod.so\" twice:"); - OUT; - - fp = dlsym (h[2], "foo"); - puts ("\nnow calling `foo'"); - fflush (stdout); - fp (); - puts ("managed to call `foo'"); - fflush (stdout); - - dlclose (h[2]); - - puts ("\nAfter unloading \"unload2dep.so\":"); - OUT; - - return 0; -} diff --git a/elf/unload2dep.c b/elf/unload2dep.c deleted file mode 100644 index 0d319515d5..0000000000 --- a/elf/unload2dep.c +++ /dev/null @@ -1,6 +0,0 @@ -extern void foo (void); - -void -foo (void) -{ -} diff --git a/elf/unload2mod.c b/elf/unload2mod.c deleted file mode 100644 index 9c2ea586bc..0000000000 --- a/elf/unload2mod.c +++ /dev/null @@ -1,8 +0,0 @@ -extern void foo (void); -extern void bar (void); - -void -bar (void) -{ - foo (); -} diff --git a/elf/unload3.c b/elf/unload3.c deleted file mode 100644 index 6f1af707e6..0000000000 --- a/elf/unload3.c +++ /dev/null @@ -1,41 +0,0 @@ -#include <dlfcn.h> -#include <stdio.h> - -int -main (void) -{ - void *g = dlopen ("unload3mod1.so", RTLD_GLOBAL | RTLD_NOW); - void *h = dlopen ("unload3mod2.so", RTLD_GLOBAL | RTLD_NOW); - if (g == NULL || h == NULL) - { - printf ("dlopen unload3mod{1,2}.so failed: %p %p\n", g, h); - return 1; - } - dlclose (h); - dlclose (g); - - g = dlopen ("unload3mod3.so", RTLD_GLOBAL | RTLD_NOW); - h = dlopen ("unload3mod4.so", RTLD_GLOBAL | RTLD_NOW); - if (g == NULL || h == NULL) - { - printf ("dlopen unload3mod{3,4}.so failed: %p %p\n", g, h); - return 1; - } - - int (*fn) (int); - fn = dlsym (h, "bar"); - if (fn == NULL) - { - puts ("dlsym failed"); - return 1; - } - - int val = fn (16); - if (val != 24) - { - printf ("bar returned %d != 24\n", val); - return 1; - } - - return 0; -} diff --git a/elf/unload3mod1.c b/elf/unload3mod1.c deleted file mode 100644 index e886b11c18..0000000000 --- a/elf/unload3mod1.c +++ /dev/null @@ -1 +0,0 @@ -int dummy1; diff --git a/elf/unload3mod2.c b/elf/unload3mod2.c deleted file mode 100644 index 03252a523b..0000000000 --- a/elf/unload3mod2.c +++ /dev/null @@ -1 +0,0 @@ -int dummy2; diff --git a/elf/unload3mod3.c b/elf/unload3mod3.c deleted file mode 100644 index 046022c55d..0000000000 --- a/elf/unload3mod3.c +++ /dev/null @@ -1,8 +0,0 @@ -#include <stdio.h> - -int -foo (int x) -{ - puts ("foo"); - return x * 2; -} diff --git a/elf/unload3mod4.c b/elf/unload3mod4.c deleted file mode 100644 index 52f808e79b..0000000000 --- a/elf/unload3mod4.c +++ /dev/null @@ -1,13 +0,0 @@ -#include <stdio.h> - -extern int foo (int x); - -int -bar (int x) -{ - puts ("bar"); - fflush (stdout); - x = foo (x - 4); - puts ("bar after foo"); - return x; -} diff --git a/elf/unload4.c b/elf/unload4.c deleted file mode 100644 index 6e171a22e0..0000000000 --- a/elf/unload4.c +++ /dev/null @@ -1,48 +0,0 @@ -#include <dlfcn.h> -#include <stdio.h> -#include <malloc.h> - -int -main (void) -{ -#ifdef M_PERTURB - mallopt (M_PERTURB, 0xaa); -#endif - - void *h; - int (*fn) (int); - h = dlopen ("unload4mod1.so", RTLD_LAZY); - if (h == NULL) - { - puts ("1st dlopen failed"); - return 1; - } - fn = dlsym (h, "foo"); - if (fn == NULL) - { - puts ("dlsym failed"); - return 1; - } - int n = fn (10); - if (n != 28) - { - printf ("foo (10) returned %d != 28\n", n); - return 1; - } - dlclose (h); - h = dlopen ("unload4mod3.so", RTLD_LAZY); - fn = dlsym (h, "mod3fn2"); - if (fn == NULL) - { - puts ("second dlsym failed"); - return 1; - } - n = fn (10); - if (n != 22) - { - printf ("mod3fn2 (10) returned %d != 22\n", n); - return 1; - } - dlclose (h); - return 0; -} diff --git a/elf/unload4mod1.c b/elf/unload4mod1.c deleted file mode 100644 index 38c5b0168d..0000000000 --- a/elf/unload4mod1.c +++ /dev/null @@ -1,10 +0,0 @@ -#include <stdio.h> - -extern int bar (int); - -int -foo (int x) -{ - puts ("in foo"); - return bar (x / 2) + 2; -} diff --git a/elf/unload4mod2.c b/elf/unload4mod2.c deleted file mode 100644 index 497ef5d93b..0000000000 --- a/elf/unload4mod2.c +++ /dev/null @@ -1,8 +0,0 @@ -#include <stdio.h> - -int -baz (int x) -{ - puts ("in baz"); - return x * 4; -} diff --git a/elf/unload4mod3.c b/elf/unload4mod3.c deleted file mode 100644 index 4b280bc05b..0000000000 --- a/elf/unload4mod3.c +++ /dev/null @@ -1,16 +0,0 @@ -#include <stdio.h> - -int -__attribute__((noinline)) -mod3fn1 (int x) -{ - puts ("in mod3fn1"); - return x + 6; -} - -int -mod3fn2 (int x) -{ - puts ("in mod3fn2"); - return mod3fn1 (x / 2) * 2; -} diff --git a/elf/unload4mod4.c b/elf/unload4mod4.c deleted file mode 100644 index ba5a144d38..0000000000 --- a/elf/unload4mod4.c +++ /dev/null @@ -1,16 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> - -int -__attribute__((noinline)) -baz (int x) -{ - abort (); -} - -int -bar (int x) -{ - puts ("in bar"); - return baz (x + 1) + 2; -} diff --git a/elf/unload5.c b/elf/unload5.c deleted file mode 100644 index 0555052ce8..0000000000 --- a/elf/unload5.c +++ /dev/null @@ -1,42 +0,0 @@ -#include <dlfcn.h> -#include <stdio.h> - -int -main (void) -{ - void *g = dlopen ("unload3mod1.so", RTLD_GLOBAL | RTLD_NOW); - void *h = dlopen ("unload3mod2.so", RTLD_GLOBAL | RTLD_NOW); - if (g == NULL || h == NULL) - { - printf ("dlopen unload3mod{1,2}.so failed: %p %p\n", g, h); - return 1; - } - dlopen ("unload3mod4.so", RTLD_GLOBAL | RTLD_NOW); - dlclose (h); - dlclose (g); - - g = dlopen ("unload3mod3.so", RTLD_GLOBAL | RTLD_NOW); - h = dlopen ("unload3mod4.so", RTLD_GLOBAL | RTLD_NOW); - if (g == NULL || h == NULL) - { - printf ("dlopen unload3mod{3,4}.so failed: %p %p\n", g, h); - return 1; - } - - int (*fn) (int); - fn = dlsym (h, "bar"); - if (fn == NULL) - { - puts ("dlsym failed"); - return 1; - } - - int val = fn (16); - if (val != 24) - { - printf ("bar returned %d != 24\n", val); - return 1; - } - - return 0; -} diff --git a/elf/unload6.c b/elf/unload6.c deleted file mode 100644 index 1efc7eb841..0000000000 --- a/elf/unload6.c +++ /dev/null @@ -1,30 +0,0 @@ -#include <dlfcn.h> -#include <stdio.h> - -int -main (void) -{ - void *h = dlopen ("unload6mod1.so", RTLD_LAZY); - if (h == NULL) - { - puts ("dlopen unload6mod1.so failed"); - return 1; - } - - int (*fn) (int); - fn = dlsym (h, "foo"); - if (fn == NULL) - { - puts ("dlsym failed"); - return 1; - } - - int val = fn (16); - if (val != 24) - { - printf ("foo returned %d != 24\n", val); - return 1; - } - - return 0; -} diff --git a/elf/unload6mod1.c b/elf/unload6mod1.c deleted file mode 100644 index 24f2e5a19a..0000000000 --- a/elf/unload6mod1.c +++ /dev/null @@ -1,16 +0,0 @@ -#include <dlfcn.h> -#include <stdio.h> - -int -foo (int i) -{ - void *h = dlopen ("unload6mod2.so", RTLD_LAZY); - if (h == NULL) - { - puts ("dlopen unload6mod2.so failed"); - return 1; - } - - dlclose (h); - return i + 8; -} diff --git a/elf/unload6mod2.c b/elf/unload6mod2.c deleted file mode 100644 index 980efa4b0e..0000000000 --- a/elf/unload6mod2.c +++ /dev/null @@ -1,23 +0,0 @@ -#include <dlfcn.h> -#include <stdio.h> -#include <unistd.h> - -static void *h; - -static void __attribute__((constructor)) -mod2init (void) -{ - h = dlopen ("unload6mod3.so", RTLD_LAZY); - if (h == NULL) - { - puts ("dlopen unload6mod3.so failed"); - fflush (stdout); - _exit (1); - } -} - -static void __attribute__((destructor)) -mod2fini (void) -{ - dlclose (h); -} diff --git a/elf/unload6mod3.c b/elf/unload6mod3.c deleted file mode 100644 index 7b29e1d626..0000000000 --- a/elf/unload6mod3.c +++ /dev/null @@ -1,23 +0,0 @@ -#include <dlfcn.h> -#include <stdio.h> -#include <unistd.h> - -static void *h; - -static void __attribute__((constructor)) -mod3init (void) -{ - h = dlopen ("unload6mod1.so", RTLD_LAZY); - if (h == NULL) - { - puts ("dlopen unload6mod1.so failed"); - fflush (stdout); - _exit (1); - } -} - -static void __attribute__((destructor)) -mod3fini (void) -{ - dlclose (h); -} diff --git a/elf/unload7.c b/elf/unload7.c deleted file mode 100644 index 198f7db286..0000000000 --- a/elf/unload7.c +++ /dev/null @@ -1,39 +0,0 @@ -#include <dlfcn.h> -#include <stdio.h> - -int -main (void) -{ - void *h = dlopen ("$ORIGIN/unload7mod1.so", RTLD_LAZY); - if (h == NULL) - { - puts ("dlopen unload7mod1.so failed"); - return 1; - } - - int (*fn) (void); - fn = dlsym (h, "foo"); - if (fn == NULL) - { - puts ("dlsym failed"); - return 1; - } - - int ret = 0; - if (fn () == 0) - ++ret; - - void *h2 = dlopen ("$ORIGIN/unload7mod2.so", RTLD_LAZY); - if (h2 == NULL) - { - puts ("dlopen unload7mod2.so failed"); - return 1; - } - dlclose (h2); - - if (fn () == 0) - ++ret; - - dlclose (h); - return ret; -} diff --git a/elf/unload7mod1.c b/elf/unload7mod1.c deleted file mode 100644 index 7435adce2c..0000000000 --- a/elf/unload7mod1.c +++ /dev/null @@ -1,11 +0,0 @@ -#include <dlfcn.h> -#include <stdio.h> - -int -foo (int i) -{ - if (dlsym (RTLD_DEFAULT, "unload7_nonexistent_symbol") == NULL) - return 1; - puts ("dlsym returned non-NULL"); - return 0; -} diff --git a/elf/unload7mod2.c b/elf/unload7mod2.c deleted file mode 100644 index 6d1a0d47b7..0000000000 --- a/elf/unload7mod2.c +++ /dev/null @@ -1 +0,0 @@ -int x; diff --git a/elf/unload8.c b/elf/unload8.c deleted file mode 100644 index f984a38098..0000000000 --- a/elf/unload8.c +++ /dev/null @@ -1,33 +0,0 @@ -#include <dlfcn.h> -#include <stdio.h> - -int -main (void) -{ - void *h = dlopen ("$ORIGIN/unload8mod1.so", RTLD_LAZY); - if (h == NULL) - { - puts ("dlopen unload8mod1.so failed"); - return 1; - } - - void *h2 = dlopen ("$ORIGIN/unload8mod1x.so", RTLD_LAZY); - if (h2 == NULL) - { - puts ("dlopen unload8mod1x.so failed"); - return 1; - } - dlclose (h2); - - int (*mod1) (void) = dlsym (h, "mod1"); - if (mod1 == NULL) - { - puts ("dlsym failed"); - return 1; - } - - mod1 (); - dlclose (h); - - return 0; -} diff --git a/elf/unload8mod1.c b/elf/unload8mod1.c deleted file mode 100644 index fe7e81c1c3..0000000000 --- a/elf/unload8mod1.c +++ /dev/null @@ -1,7 +0,0 @@ -extern void mod2 (void); - -void -mod1 (void) -{ - mod2 (); -} diff --git a/elf/unload8mod1x.c b/elf/unload8mod1x.c deleted file mode 100644 index 835b634914..0000000000 --- a/elf/unload8mod1x.c +++ /dev/null @@ -1 +0,0 @@ -int mod1x; diff --git a/elf/unload8mod2.c b/elf/unload8mod2.c deleted file mode 100644 index 2fd8b6768a..0000000000 --- a/elf/unload8mod2.c +++ /dev/null @@ -1,7 +0,0 @@ -extern void mod3 (void); - -void -mod2 (void) -{ - mod3 (); -} diff --git a/elf/unload8mod3.c b/elf/unload8mod3.c deleted file mode 100644 index d49e22b24c..0000000000 --- a/elf/unload8mod3.c +++ /dev/null @@ -1,27 +0,0 @@ -#include <dlfcn.h> -#include <stdio.h> -#include <stdlib.h> - -void -mod3_fini2 (void) -{ -} - -void -mod3_fini (void) -{ - mod3_fini2 (); -} - -void -mod3 (void) -{ - void *h = dlopen ("$ORIGIN/unload8mod2.so", RTLD_LAZY); - if (h == NULL) - { - puts ("dlopen unload8mod2.so failed"); - exit (1); - } - - atexit (mod3_fini); -} diff --git a/elf/unloadmod.c b/elf/unloadmod.c deleted file mode 100644 index 3aa5403edf..0000000000 --- a/elf/unloadmod.c +++ /dev/null @@ -1,4 +0,0 @@ -struct testdat -{ - void *next; -} testdat; diff --git a/elf/vismain.c b/elf/vismain.c deleted file mode 100644 index 43f1d8f095..0000000000 --- a/elf/vismain.c +++ /dev/null @@ -1,260 +0,0 @@ -/* Copyright (C) 2000-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -/* 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 "vismod.h" - -/* Prototype for our test function. */ -extern int do_test (void); - - -/* This defines the `main' function and some more. */ -#include <support/test-driver.c> - - -/* Prototypes for local functions. */ -extern int protlocal (void); - -const char *protvarlocal = __FILE__; -extern const char *protvarinmod; -extern const char *protvaritcpt; - -int -do_test (void) -{ - int res = 0; - int val; - - /* First test: check whether .protected is handled correctly by the - assembler/linker. The uses of `protlocal' in the DSOs and in the - main program should all be resolved with the local definitions. */ - val = protlocal () + calllocal1 () + calllocal2 (); - if (val != 0x155) - { - puts ("\ -The handling of `.protected' seems to be implemented incorrectly: giving up"); - abort (); - } - puts ("`.protected' seems to be handled correctly, good!"); - - /* Function pointers: for functions which are marked local and for - which definitions are available all function pointers must be - distinct. */ - if (protlocal == getlocal1 ()) - { - puts ("`protlocal' in main and mod1 have same address"); - res = 1; - } - if (protlocal == getlocal2 ()) - { - puts ("`protlocal' in main and mod2 have same address"); - res = 1; - } - if (getlocal1 () == getlocal2 ()) - { - puts ("`protlocal' in mod1 and mod2 have same address"); - res = 1; - } - if (getlocal1 () () + getlocal2 () () != 0x44) - { - puts ("pointers to `protlocal' in mod1 or mod2 incorrect"); - res = 1; - } - - /* Next test. This is similar to the last one but the function we - are calling is not defined in the main object. This means that - the invocation in the main object uses the definition in the - first DSO. */ - if (protinmod != getinmod1 ()) - { - printf ("&protinmod in main (%p) != &protinmod in mod1 (%p)\n", - protinmod, getinmod1 ()); - res = 1; - } - if (protinmod == getinmod2 ()) - { - puts ("`protinmod' in main and mod2 have same address"); - res = 1; - } - if (getinmod1 () == getinmod2 ()) - { - puts ("`protinmod' in mod1 and mod2 have same address"); - res = 1; - } - if (protinmod () + getinmod1 () () + getinmod2 () () != 0x4800) - { - puts ("pointers to `protinmod' in mod1 or mod2 incorrect"); - res = 1; - } - val = protinmod () + callinmod1 () + callinmod2 (); - if (val != 0x15800) - { - printf ("calling of `protinmod' leads to wrong result (%#x)\n", val); - res = 1; - } - - /* A very similar text. Same setup for the main object and the modules - but this time we have another definition in a preloaded module. This - one intercepts the references from the main object. */ - if (protitcpt != getitcpt3 ()) - { - printf ("&protitcpt in main (%p) != &protitcpt in mod3 (%p)\n", - &protitcpt, getitcpt3 ()); - res = 1; - } - if (protitcpt == getitcpt1 ()) - { - puts ("`protitcpt' in main and mod1 have same address"); - res = 1; - } - if (protitcpt == getitcpt2 ()) - { - puts ("`protitcpt' in main and mod2 have same address"); - res = 1; - } - if (getitcpt1 () == getitcpt2 ()) - { - puts ("`protitcpt' in mod1 and mod2 have same address"); - res = 1; - } - val = protitcpt () + getitcpt1 () () + getitcpt2 () () + getitcpt3 () (); - if (val != 0x8440000) - { - printf ("\ -pointers to `protitcpt' in mod1 or mod2 or mod3 incorrect (%#x)\n", val); - res = 1; - } - val = protitcpt () + callitcpt1 () + callitcpt2 () + callitcpt3 (); - if (val != 0x19540000) - { - printf ("calling of `protitcpt' leads to wrong result (%#x)\n", val); - res = 1; - } - - /* Now look at variables. First a variable which is available - everywhere. We must have three different addresses. */ - if (&protvarlocal == getvarlocal1 ()) - { - puts ("`protvarlocal' in main and mod1 have same address"); - res = 1; - } - if (&protvarlocal == getvarlocal2 ()) - { - puts ("`protvarlocal' in main and mod2 have same address"); - res = 1; - } - if (getvarlocal1 () == getvarlocal2 ()) - { - puts ("`protvarlocal' in mod1 and mod2 have same address"); - res = 1; - } - if (strcmp (protvarlocal, __FILE__) != 0) - { - puts ("`protvarlocal in main has wrong value"); - res = 1; - } - if (strcmp (*getvarlocal1 (), "vismod1.c") != 0) - { - puts ("`getvarlocal1' returns wrong value"); - res = 1; - } - if (strcmp (*getvarlocal2 (), "vismod2.c") != 0) - { - puts ("`getvarlocal2' returns wrong value"); - res = 1; - } - - /* Now the case where there is no local definition. */ - if (&protvarinmod != getvarinmod1 ()) - { - printf ("&protvarinmod in main (%p) != &protitcpt in mod1 (%p)\n", - &protvarinmod, getvarinmod1 ()); - // XXX Possibly enable once fixed. - // res = 1; - } - if (&protvarinmod == getvarinmod2 ()) - { - puts ("`protvarinmod' in main and mod2 have same address"); - res = 1; - } - if (strcmp (*getvarinmod1 (), "vismod1.c") != 0) - { - puts ("`getvarinmod1' returns wrong value"); - res = 1; - } - if (strcmp (*getvarinmod2 (), "vismod2.c") != 0) - { - puts ("`getvarinmod2' returns wrong value"); - res = 1; - } - - /* And a test where a variable definition is intercepted. */ - if (&protvaritcpt == getvaritcpt1 ()) - { - puts ("`protvaritcpt' in main and mod1 have same address"); - res = 1; - } - if (&protvaritcpt == getvaritcpt2 ()) - { - puts ("`protvaritcpt' in main and mod2 have same address"); - res = 1; - } - if (&protvaritcpt != getvaritcpt3 ()) - { - printf ("&protvaritcpt in main (%p) != &protvaritcpt in mod3 (%p)\n", - &protvaritcpt, getvaritcpt3 ()); - // XXX Possibly enable once fixed. - // res = 1; - } - if (getvaritcpt1 () == getvaritcpt2 ()) - { - puts ("`protvaritcpt' in mod1 and mod2 have same address"); - res = 1; - } - if (strcmp (protvaritcpt, "vismod3.c") != 0) - { - puts ("`protvaritcpt in main has wrong value"); - res = 1; - } - if (strcmp (*getvaritcpt1 (), "vismod1.c") != 0) - { - puts ("`getvaritcpt1' returns wrong value"); - res = 1; - } - if (strcmp (*getvaritcpt2 (), "vismod2.c") != 0) - { - puts ("`getvaritcpt2' returns wrong value"); - res = 1; - } - - return res; -} - - -int -protlocal (void) -{ - return 0x1; -} diff --git a/elf/vismod.h b/elf/vismod.h deleted file mode 100644 index ef05ffd5e9..0000000000 --- a/elf/vismod.h +++ /dev/null @@ -1,27 +0,0 @@ -/* Prototypes for the functions in the DSOs. */ -extern int calllocal1 (void); -extern int (*getlocal1 (void)) (void); -extern int callinmod1 (void); -extern int (*getinmod1 (void)) (void); -extern int callitcpt1 (void); -extern int (*getitcpt1 (void)) (void); -extern const char **getvarlocal1 (void); -extern const char **getvarinmod1 (void); -extern const char **getvaritcpt1 (void); -extern int calllocal2 (void); -extern int (*getlocal2 (void)) (void); -extern int callinmod2 (void); -extern int (*getinmod2 (void)) (void); -extern int callitcpt2 (void); -extern int (*getitcpt2 (void)) (void); -extern const char **getvarlocal2 (void); -extern const char **getvarinmod2 (void); -extern const char **getvaritcpt2 (void); -extern int callitcpt3 (void); -extern int (*getitcpt3 (void)) (void); -extern const char **getvaritcpt3 (void); - -extern int protinmod (void); -extern int protitcpt (void); -extern int protlocal (void); - diff --git a/elf/vismod1.c b/elf/vismod1.c deleted file mode 100644 index 3e56404ce7..0000000000 --- a/elf/vismod1.c +++ /dev/null @@ -1,103 +0,0 @@ -/* Copyright (C) 2000-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -#include "vismod.h" - -int -protlocal (void) -{ - return 0x4; -} -asm (".protected protlocal"); - - -int -calllocal1 (void) -{ - return protlocal () + 0x10; -} - -int -(*getlocal1 (void)) (void) -{ - return protlocal; -} - -int -protinmod (void) -{ - return 0x400; -} -asm (".protected protinmod"); - -int -callinmod1 (void) -{ - return protinmod () + 0x1000; -} - -int -(*getinmod1 (void)) (void) -{ - return protinmod; -} - -int -protitcpt (void) -{ - return 0x40000; -} -asm (".protected protitcpt"); - -int -callitcpt1 (void) -{ - return protitcpt () + 0x100000; -} - -int -(*getitcpt1 (void)) (void) -{ - return protitcpt; -} - -const char *protvarlocal = __FILE__; -asm (".protected protvarlocal"); - -const char ** -getvarlocal1 (void) -{ - return &protvarlocal; -} - -const char *protvarinmod = __FILE__; -asm (".protected protvarinmod"); - -const char ** -getvarinmod1 (void) -{ - return &protvarinmod; -} - -const char *protvaritcpt = __FILE__; -asm (".protected protvaritcpt"); - -const char ** -getvaritcpt1 (void) -{ - return &protvaritcpt; -} diff --git a/elf/vismod2.c b/elf/vismod2.c deleted file mode 100644 index 89be69728a..0000000000 --- a/elf/vismod2.c +++ /dev/null @@ -1,123 +0,0 @@ -/* Copyright (C) 2000-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -#include <stdlib.h> -#include "vismod.h" - -int -protlocal (void) -{ - return 0x40; -} -asm (".protected protlocal"); - - -int -calllocal2 (void) -{ - return protlocal () + 0x100; -} - -int -(*getlocal2 (void)) (void) -{ - return protlocal; -} - -int -protinmod (void) -{ - return 0x4000; -} -asm (".protected protinmod"); - -int -callinmod2 (void) -{ - return protinmod () + 0x10000; -} - -int -(*getinmod2 (void)) (void) -{ - return protinmod; -} - -int -protitcpt (void) -{ - return 0x400000; -} -asm (".protected protitcpt"); - -int -callitcpt2 (void) -{ - return protitcpt () + 0x1000000; -} - -int -(*getitcpt2 (void)) (void) -{ - return protitcpt; -} - -const char *protvarlocal = __FILE__; -asm (".protected protvarlocal"); - -const char ** -getvarlocal2 (void) -{ - return &protvarlocal; -} - -const char *protvarinmod = __FILE__; -asm (".protected protvarinmod"); - -const char ** -getvarinmod2 (void) -{ - return &protvarinmod; -} - -const char *protvaritcpt = __FILE__; -asm (".protected protvaritcpt"); - -const char ** -getvaritcpt2 (void) -{ - return &protvaritcpt; -} - -/* We must never call these functions. */ -int -callitcpt3 (void) -{ - abort (); -} - -int -(*getitcpt3 (void)) (void) -{ - abort (); -} - -const char ** -getvaritcpt3 (void) -{ - abort (); -} diff --git a/elf/vismod3.c b/elf/vismod3.c deleted file mode 100644 index 1074d1bcda..0000000000 --- a/elf/vismod3.c +++ /dev/null @@ -1,46 +0,0 @@ -/* Copyright (C) 2000-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -#include "vismod.h" - -int -protitcpt (void) -{ - return 0x4000000; -} -asm (".protected protitcpt"); - -int -callitcpt3 (void) -{ - return protitcpt () + 0x10000000; -} - -int -(*getitcpt3 (void)) (void) -{ - return protitcpt; -} - -const char *protvaritcpt = __FILE__; -asm (".protected protvaritcpt"); - -const char ** -getvaritcpt3 (void) -{ - return &protvaritcpt; -} |