From ce460d04a5bd10d7353ca37dfa9d34275449fb3b Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Fri, 11 Oct 2002 10:52:20 +0000 Subject: * sysdeps/generic/bits/libc-tsd.h [USE___THREAD]: Conditional changed from [USE_TLS && HAVE___THREAD]. * sysdeps/i386/dl-machine.h (elf_machine_type_class, elf_machine_rel): Disable TLS relocs if [RTLD_BOOTSTRAP && !USE___THREAD]. * sysdeps/x86_64/dl-machine.h (elf_machine_type_class, elf_machine_rela): Likewise. * sysdeps/sh/dl-machine.h (elf_machine_type_class, elf_machine_rela): Likewise. * include/link.h (struct link_map): Remove member l_tls_tp_initialized. * elf/rtld.c (_dl_start_final, dl_main): Don't use it. (_dl_start): Conditionalize PT_TLS check on [USE___THREAD]. * sysdeps/i386/dl-tls.h (__TLS_GET_ADDR): Use ___tls_get_addr_internal instead of ___tls_get_addr. (___tls_get_addr_internal): Add attribute_hidden to decl. * sysdeps/generic/ldsodefs.h (struct rtld_global): New variable _dl_error_catch_tsd. * elf/rtld.c (startup_error_tsd): New function. (dl_main): Point _dl_error_catch_tsd at that. * elf/dl-error.c: Don't use libc-tsd.h for DL_ERROR, use new function pointer instead. * elf/dl-tsd.c: New file. * elf/Makefile (routines): Add it. 2002-10-07 Roland McGrath * elf/dl-misc.c (_dl_debug_vdprintf): Use INTERNAL_SYSCALL macro for writev if it's available. Otherwise if [RTLD_PRIVATE_ERRNO] then take _dl_load_lock around calling __writev. * sysdeps/unix/sysv/linux/i386/sysdep.h (INTERNAL_SYSCALL): New macro. (INLINE_SYSCALL): Use that. * sysdeps/generic/dl-sysdep.h: New file. * sysdeps/mach/hurd/dl-sysdep.h: New file. * sysdeps/generic/ldsodefs.h: Include . * include/errno.h [IS_IN_rtld]: Include to define ... [RTLD_PRIVATE_ERRNO]: Use a hidden global variable for errno and access it directly. * elf/dl-minimal.c (__errno_location): Removed. * sysdeps/unix/i386/sysdep.S (__syscall_errno) [RTLD_PRIVATE_ERRNO]: Use GOTOFF access for errno. * sysdeps/unix/sysv/linux/i386/sysdep.h [RTLD_PRIVATE_ERRNO] (SYSCALL_ERROR_HANDLER): Likewise. * sysdeps/unix/x86_64/sysdep.S (__syscall_errno) [RTLD_PRIVATE_ERRNO]: Use PC-relative access for errno. * sysdeps/unix/sysv/linux/x86_64/sysdep.h [RTLD_PRIVATE_ERRNO] (SYSCALL_ERROR_HANDLER): Likewise. * include/tls.h: New file. (USE___THREAD): New macro. Define to 1 under [USE_TLS && HAVE___THREAD] and only when compiling libc or libpthread. * sysdeps/unix/sysv/linux/i386/sysdep.h [USE___THREAD]: Conditional changed from [USE_TLS && HAVE___THREAD]. * sysdeps/unix/sysv/linux/x86_64/sysdep.h: Likewise. * sysdeps/unix/i386/sysdep.S: Likewise. * sysdeps/unix/x86_64/sysdep.S: Likewise. * include/errno.h: Likewise. * include/netdb.h: Likewise. * include/resolv.h: Likewise. * sysdeps/generic/errno.c: New file. * csu/Makefile (aux): New variable, list errno. * sysdeps/unix/sysv/linux/i386/sysdep.S (errno, _errno): Remove defns. * sysdeps/unix/sysv/linux/m68k/sysdep.S: Likewise. * sysdeps/unix/sysv/linux/x86_64/sysdep.S: Likewise. * sysdeps/unix/sysv/linux/s390/s390-64/sysdep.S: Likewise. * sysdeps/unix/sysv/linux/s390/s390-32/sysdep.S: Likewise. * sysdeps/unix/sysv/linux/arm/sysdep.S: Likewise. * sysdeps/unix/sysv/linux/cris/sysdep.S: Likewise. * sysdeps/unix/sysv/linux/hppa/sysdep.c: Likewise. * sysdeps/unix/sysv/linux/ia64/sysdep.S: Likewise. * sysdeps/unix/sysv/linux/powerpc/sysdep.c: Likewise. * sysdeps/unix/sysv/linux/sparc/sysdep.S: Likewise. * sysdeps/unix/sysv/linux/sh/sysdep.S: Likewise. * sysdeps/unix/alpha/sysdep.S: Likewise. * sysdeps/generic/start.c: Likewise. * sysdeps/unix/start.c: Likewise. * sysdeps/unix/arm/start.c: Likewise. * sysdeps/unix/bsd/ultrix4/mips/start.S: Likewise. * sysdeps/unix/sparc/start.c: Likewise. * sysdeps/unix/sysv/irix4/start.c: Likewise. * sysdeps/unix/sysv/linux/mips/sysdep.S: File removed. * manual/search.texi (Tree Search Function, Hash Search Function): Mention search.h clearly. 2002-10-05 Roland McGrath * elf/dl-fxstat64.c: File removed. * elf/dl-xstat64.c: File removed. * elf/Makefile (rtld-routines): Remove them. * sysdeps/unix/sysv/linux/xstat64.c: Remove RTLD_STAT64 conditionals. Instead, use strong_alias instead of versioned_symbol in the !SHLIB_COMPAT case. * sysdeps/unix/sysv/linux/fxstat64.c: Likewise. * sysdeps/unix/sysv/linux/lxstat64.c: Likewise. * include/shlib-compat.h (SHLIB_COMPAT): Require that IS_IN_##lib be defined nonzero. [! NOT_IN_libc] (IS_IN_libc): Define it. * cppflags-iterator.mk (CPPFLAGS-$(cpp-src)): Use -Dx=1 not just -Dx. * elf/Makefile (CPPFLAGS-.os): Likewise. * sunrpc/rpc_main.c (main): Don't declare with noreturn attribute. Return the status instead of calling exit. * Makeconfig (CFLAGS): Prepend -std=gnu99. * Makerules (+make-deps): Use $(CFLAGS) only for .c sources. Remove superfluous rm command, whose @ plus make bugs hid all these commands from the make output. * include/stubs-prologue.h: New file. Give #error under #ifdef _LIBC. * Makefile ($(inst_includedir)/gnu/stubs.h): Depend on it. Use that file's contents instead of literal echo's for the prologue. * include/features.h: Include unconditionally. * include/gnu/stubs.h: New file. 2002-09-30 Roland McGrath * elf/rtld-Rules: New file. * elf/Makefile ($(objpfx)librtld.map, $(objpfx)librtld.mk, $(objpfx)rtld-libc.a): New targets. (generated): Add them. (reloc-link): Remove -o $@ from the variable. ($(objpfx)dl-allobjs.os): Add -o $@ after $(reloc-link). (distribute): Add rtld-Rules. (CPPFLAGS-.os): Define this instead of CFLAGS-.os. * Makerules ($(+sysdir_pfx)sysd-rules): Emit rules for rtld-% targets. (common-mostlyclean, common-clean): Clean up rtld-* files. * sysdeps/unix/make-syscalls.sh: Add rtld-*.os target name to rules. --- elf/Makefile | 54 ++++++++++++++++++++----- elf/dl-error.c | 26 ++++++------ elf/dl-fxstat64.c | 25 ------------ elf/dl-minimal.c | 16 -------- elf/dl-misc.c | 11 ++++++ elf/dl-tsd.c | 54 +++++++++++++++++++++++++ elf/dl-xstat64.c | 25 ------------ elf/rtld-Rules | 115 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ elf/rtld.c | 83 +++++++++++++++++---------------------- 9 files changed, 273 insertions(+), 136 deletions(-) delete mode 100644 elf/dl-fxstat64.c create mode 100644 elf/dl-tsd.c delete mode 100644 elf/dl-xstat64.c create mode 100644 elf/rtld-Rules (limited to 'elf') diff --git a/elf/Makefile b/elf/Makefile index 5470728ae7..5fdcec46df 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -23,7 +23,7 @@ subdir := elf headers = elf.h bits/elfclass.h link.h routines = $(dl-routines) dl-open dl-close dl-support dl-iteratephdr \ dl-iteratephdr-static dl-addr enbl-secure dl-profstub \ - dl-origin dl-libc dl-sym + dl-origin dl-libc dl-sym dl-tsd # The core dynamic linking functions are in libc for the static and # profiled libraries. @@ -37,11 +37,11 @@ elide-routines.os = $(all-dl-routines) dl-support enbl-secure \ # ld.so uses those routines, plus some special stuff for being the program # interpreter and operating independent of libc. -rtld-routines := rtld $(dl-routines) dl-sysdep dl-environ dl-minimal \ - dl-xstat64 dl-fxstat64 +rtld-routines := rtld $(dl-routines) dl-sysdep dl-environ dl-minimal all-rtld-routines = $(rtld-routines) $(sysdep-rtld-routines) -distribute := $(rtld-routines:=.c) dynamic-link.h do-rel.h dl-machine.h \ +distribute := rtld-Rules \ + $(rtld-routines:=.c) dynamic-link.h do-rel.h dl-machine.h \ dl-cache.h dl-hash.h soinit.c sofini.c ldd.bash.in \ genrtldtbl.awk atomicity.h dl-procinfo.h ldsodefs.h \ dl-librecon.h interp.c sln.c dl-dst.h hp-timing.h \ @@ -166,14 +166,49 @@ lib-noranlib: $(objpfx)$(rtld-installed-name) \ endif # Command to link into a larger single relocatable object. -reloc-link = $(LINK.o) -nostdlib -nostartfiles -r -o $@ +reloc-link = $(LINK.o) -nostdlib -nostartfiles -r $(objpfx)dl-allobjs.os: $(all-rtld-routines:%=$(objpfx)%.os) - $(reloc-link) $^ + $(reloc-link) -o $@ $^ # Link together the dynamic linker into a single relocatable object. -$(objpfx)librtld.os: $(objpfx)dl-allobjs.os $(common-objpfx)libc_pic.a - $(reloc-link) '-Wl,-(' $^ -lgcc '-Wl,-)' +# 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. + +$(objpfx)librtld.map: $(objpfx)dl-allobjs.os $(common-objpfx)libc_pic.a + $(reloc-link) -o $@.o '-Wl,-(' $^ -lgcc '-Wl,-)' -Wl,-Map,$@ + rm -f $@.o + +$(objpfx)librtld.mk: $(objpfx)librtld.map Makefile + sed -n 's@^$(common-objpfx)\([^(]*\)(\(.*.os\))$$@\1 \2@p' $< | \ + while read lib file; do \ + case $$lib in \ + libc_pic.a) \ + fgrep -l /$$file \ + $(common-objpfx)stamp.os $(common-objpfx)*/stamp.os | \ + 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 = `sed 's/^rtld-\([^ ]*\).*$$/\1/' $@T \ + | sort -u` >> $@T + mv -f $@T $@ + +$(objpfx)rtld-libc.a: $(objpfx)librtld.mk FORCE + $(MAKE) -f $< -f rtld-Rules + +generated += librtld.map librtld.mk rtld-libc.a + +$(objpfx)librtld.os: $(objpfx)dl-allobjs.os $(objpfx)rtld-libc.a + $(LINK.o) -nostdlib -nostartfiles -r -o $@ '-Wl,-(' $^ -lgcc '-Wl,-)' $(objpfx)ld.so: $(objpfx)librtld.os $(ld-map) @rm -f $@.lds @@ -209,6 +244,7 @@ $(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). @@ -265,7 +301,7 @@ CFLAGS-ldconfig.c = $(SYSCONF-FLAGS) -D'LIBDIR="$(libdir)"' -D'SLIBDIR="$(slibdi CFLAGS-dl-cache.c = $(SYSCONF-FLAGS) CFLAGS-cache.c = $(SYSCONF-FLAGS) -CFLAGS-.os += $(if $(filter $(@F),$(patsubst %,%.os,$(all-rtld-routines))),-DNOT_IN_libc -DIS_IN_rtld) +CPPFLAGS-.os += $(if $(filter $(@F),$(patsubst %,%.os,$(all-rtld-routines))),-DNOT_IN_libc=1 -DIS_IN_rtld=1) test-modules = $(addprefix $(objpfx),$(addsuffix .so,$(strip $(modules-names)))) generated += $(addsuffix .so,$(strip $(modules-names))) diff --git a/elf/dl-error.c b/elf/dl-error.c index 0af8f2f94b..e8f2f3e208 100644 --- a/elf/dl-error.c +++ b/elf/dl-error.c @@ -23,7 +23,6 @@ #include #include #include -#include /* This structure communicates state between _dl_catch_error and _dl_signal_error. */ @@ -38,11 +37,8 @@ struct catch 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. */ - -__libc_tsd_define (static, DL_ERROR) -#define tsd_getspecific() __libc_tsd_get (DL_ERROR) -#define tsd_setspecific(data) __libc_tsd_set (DL_ERROR, (data)) + memory. The _dl_error_catch_tsd function pointer is reset by the thread + library so that it returns the address of a thread-local variable. */ /* This message we return as a last resort. We define the string in a @@ -72,7 +68,7 @@ _dl_signal_error (int errcode, const char *objname, const char *occation, if (! errstring) errstring = N_("DYNAMIC LINKER BUG!!!"); - lcatch = tsd_getspecific (); + lcatch = *((*GL(dl_error_catch_tsd)) ()); if (objname == NULL) objname = ""; if (lcatch != NULL) @@ -151,20 +147,21 @@ _dl_catch_error (const char **objname, const char **errstring, inefficient. So we initialize `c' by hand. */ c.errstring = NULL; - old = tsd_getspecific (); + void **catchp = (*GL(dl_error_catch_tsd)) (); + old = *catchp; errcode = setjmp (c.env); if (__builtin_expect (errcode, 0) == 0) { - tsd_setspecific (&c); + *catchp = &c; (*operate) (args); - tsd_setspecific (old); + *catchp = old; *objname = NULL; *errstring = NULL; return 0; } /* We get here only if we longjmp'd out of OPERATE. */ - tsd_setspecific (old); + *catchp = old; *objname = c.objname; *errstring = c.errstring; return errcode == -1 ? 0 : errcode; @@ -176,18 +173,19 @@ void internal_function _dl_receive_error (receiver_fct fct, void (*operate) (void *), void *args) { + void **catchp = (*GL(dl_error_catch_tsd)) (); struct catch *old_catch; receiver_fct old_receiver; - old_catch = tsd_getspecific (); + old_catch = *catchp; old_receiver = receiver; /* Set the new values. */ - tsd_setspecific (NULL); + *catchp = NULL; receiver = fct; (*operate) (args); - tsd_setspecific (old_catch); + *catchp = old_catch; receiver = old_receiver; } diff --git a/elf/dl-fxstat64.c b/elf/dl-fxstat64.c deleted file mode 100644 index 38d445d4d4..0000000000 --- a/elf/dl-fxstat64.c +++ /dev/null @@ -1,25 +0,0 @@ -/* Dynamic linker's private version of __fxstat64. - Copyright (C) 2002 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, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ - -/* This special file is needed because some fxstat64.c implementations - use versioning for __fxstat64 and we need to keep it local to - the dynamic linker. */ - -#define RTLD_STAT64 -#include diff --git a/elf/dl-minimal.c b/elf/dl-minimal.c index f4b7e28782..d1619cfb0c 100644 --- a/elf/dl-minimal.c +++ b/elf/dl-minimal.c @@ -353,19 +353,3 @@ strong_alias (__strsep, __strsep_g) up to 36. We don't need this here. */ const char INTUSE(_itoa_lower_digits)[16] attribute_hidden = "0123456789abcdef"; - - - -#undef errno -/* The 'errno' in ld.so is not exported. */ -#if USE_TLS && HAVE___THREAD -extern __thread int errno attribute_hidden; -#else -extern int errno attribute_hidden; - -int * -__errno_location (void) -{ - return &errno; -} -#endif diff --git a/elf/dl-misc.c b/elf/dl-misc.c index 2d42230afe..f80472485d 100644 --- a/elf/dl-misc.c +++ b/elf/dl-misc.c @@ -31,6 +31,7 @@ #include #include #include +#include #ifndef MAP_ANON /* This is the only dl-sysdep.c function that is actually needed at run-time @@ -245,7 +246,17 @@ _dl_debug_vdprintf (int fd, int tag_p, const char *fmt, va_list arg) } /* Finally write the result. */ +#ifdef INTERNAL_SYSCALL + INTERNAL_SYSCALL (writev, 3, fd, iov, niov); +#elif 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. */ + __libc_lock_lock_recursive (GL(dl_load_lock)); __writev (fd, iov, niov); + __libc_lock_unlock_recursive (GL(dl_load_lock)); +#else + __writev (fd, iov, niov); +#endif } diff --git a/elf/dl-tsd.c b/elf/dl-tsd.c new file mode 100644 index 0000000000..aa290a7961 --- /dev/null +++ b/elf/dl-tsd.c @@ -0,0 +1,54 @@ +/* Thread-local data used by error handling for runtime dynamic linker. + Copyright (C) 2002 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +#ifndef SHARED + +/* _dl_error_catch_tsd points to this for the single-threaded case. + It's reset by the thread library for multithreaded programs + if we're not using __thread. */ +static void ** __attribute__ ((const)) +startup_error_tsd (void) +{ +#if USE___THREAD + static __thread void *data; +#else + static void *data; +#endif + return &data; +} +void **(*_dl_error_catch_tsd) (void) __attribute__ ((const)) + = &startup_error_tsd; + +#elif USE___THREAD + +/* libpthread sets _dl_error_catch_tsd to point to this function. + We define it here instead of in libpthread so that it doesn't + need to have a TLS segment of its own just for this one pointer. */ + +void ** __attribute__ ((const)) +__libc_dl_error_tsd (void) +{ + static __thread void *data; + return &data; +} + +#endif diff --git a/elf/dl-xstat64.c b/elf/dl-xstat64.c deleted file mode 100644 index 4484f990e0..0000000000 --- a/elf/dl-xstat64.c +++ /dev/null @@ -1,25 +0,0 @@ -/* Dynamic linker's private version of __xstat64. - Copyright (C) 2002 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, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ - -/* This special file is needed because some xstat64.c implementations - use versioning for __xstat64 and we need to keep it local to - the dynamic linker. */ - -#define RTLD_STAT64 -#include diff --git a/elf/rtld-Rules b/elf/rtld-Rules new file mode 100644 index 0000000000..03fe25d5cd --- /dev/null +++ b/elf/rtld-Rules @@ -0,0 +1,115 @@ +# Subroutine makefile for compiling libc modules linked into dynamic linker. + +# Copyright (C) 2002 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, write to the Free +# Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +# 02111-1307 USA. + +# 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. +ifeq ($(subdir),elf) + +ifndef rtld-subdirs +error This is 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 $@T $^ + $(RANLIB) $@T + mv -f $@T $@ + +# 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) -C ../$* objdir=$(objdir) -f Makefile -f ../elf/rtld-Rules rtld-all \ + rtld-modules='$(addprefix rtld-,$(rtld-$*))' +endef + +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. + +# 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: %.S $(before-compile); $(compile-command.S) +$(objpfx)rtld-%.d: %.S $(before-compile); $(+make-deps) +$(objpfx)rtld-%.os: %.s $(before-compile); $(compile-command.s) +$(objpfx)rtld-%.d: %.s $(before-compile); $(+make-deps) +$(objpfx)rtld-%.os: %.c $(before-compile); $(compile-command.c) +$(objpfx)rtld-%.d: %.c $(before-compile); $(+make-deps) + +# The rules for generated source files. +$(objpfx)rtld-%.os: $(objpfx)%.S $(before-compile); $(compile-command.S) +$(objpfx)rtld-%.d: $(objpfx)%.S $(before-compile); $(+make-deps) +$(objpfx)rtld-%.os: $(objpfx)%.s $(before-compile); $(compile-command.s) +$(objpfx)rtld-%.d: $(objpfx)%.s $(before-compile); $(+make-deps) +$(objpfx)rtld-%.os: $(objpfx)%.c $(before-compile); $(compile-command.c) +$(objpfx)rtld-%.d: $(objpfx)%.c $(before-compile); $(+make-deps) + +# 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-%.d,\ + $(filter-out $(omit-deps),\ + $(rtld-modules:rtld-%.os=%))) +ifdef rtld-depfiles +-include $(rtld-depfiles) +endif + +# Just in case we wind up e.g. regenerating dependencies for non-rtld objects, +# we don't unconditionally modify the flags. For rtld-% targets, use the +# special flags set below. +CFLAGS += $(if $(filter rtld-%,$(@F)),$(CFLAGS-rtld)) +CPPFLAGS += $(if $(filter rtld-%,$(@F)),$(CPPFLAGS-rtld)) + + +# This here is the whole point of all the shenanigans. +CPPFLAGS-rtld := -DNOT_IN_libc=1 -DIS_IN_rtld=1 +CFLAGS-rtld := # blah + + +endif diff --git a/elf/rtld.c b/elf/rtld.c index 19600644fb..3a64ca74f7 100644 --- a/elf/rtld.c +++ b/elf/rtld.c @@ -221,21 +221,18 @@ _dl_start_final (void *arg, struct dl_start_final_info *info) GL(dl_rtld_map).l_map_end = (ElfW(Addr)) _end; /* Copy the TLS related data if necessary. */ #if USE_TLS && !defined DONT_USE_BOOTSTRAP_MAP -# ifdef HAVE___THREAD +# if USE___THREAD assert (info->l.l_tls_modid != 0); + GL(dl_rtld_map).l_tls_blocksize = info->l.l_tls_blocksize; + GL(dl_rtld_map).l_tls_align = info->l.l_tls_align; + GL(dl_rtld_map).l_tls_initimage_size = info->l.l_tls_initimage_size; + GL(dl_rtld_map).l_tls_initimage = info->l.l_tls_initimage; + GL(dl_rtld_map).l_tls_offset = info->l.l_tls_offset; + GL(dl_rtld_map).l_tls_modid = 1; # else - if (info->l.l_tls_modid != 0) + assert (info->l.l_tls_modid == 0); # endif - { - GL(dl_rtld_map).l_tls_blocksize = info->l.l_tls_blocksize; - GL(dl_rtld_map).l_tls_align = info->l.l_tls_align; - GL(dl_rtld_map).l_tls_initimage_size = info->l.l_tls_initimage_size; - GL(dl_rtld_map).l_tls_initimage = info->l.l_tls_initimage; - GL(dl_rtld_map).l_tls_offset = info->l.l_tls_offset; - GL(dl_rtld_map).l_tls_modid = 1; - GL(dl_rtld_map).l_tls_tp_initialized - = info->l.l_tls_tp_initialized; - } + #endif #if HP_TIMING_AVAIL @@ -275,14 +272,6 @@ _dl_start (void *arg) #else struct dl_start_final_info info; # define bootstrap_map info.l -#endif -#if USE_TLS || (!DONT_USE_BOOTSTRAP_MAP && !HAVE_BUILTIN_MEMSET) - size_t cnt; -#endif -#ifdef USE_TLS - ElfW(Ehdr) *ehdr; - ElfW(Phdr) *phdr; - dtv_t initdtv[3]; #endif /* This #define produces dynamic linking inline functions for @@ -311,7 +300,7 @@ _dl_start (void *arg) # ifdef HAVE_BUILTIN_MEMSET __builtin_memset (bootstrap_map.l_info, '\0', sizeof (bootstrap_map.l_info)); # else - for (cnt = 0; + for (size_t cnt = 0; cnt < sizeof (bootstrap_map.l_info) / sizeof (bootstrap_map.l_info[0]); ++cnt) bootstrap_map.l_info[cnt] = 0; @@ -325,24 +314,21 @@ _dl_start (void *arg) bootstrap_map.l_ld = (void *) bootstrap_map.l_addr + elf_machine_dynamic (); elf_get_dynamic_info (&bootstrap_map); -#if USE_TLS -# if !defined HAVE___THREAD && !defined DONT_USE_BOOTSTRAP_MAP - /* Signal that we have not found TLS data so far. */ - bootstrap_map.l_tls_modid = 0; -# endif - +#if USE___THREAD /* Get the dynamic linker's own program header. First we need the ELF file header. The `_begin' symbol created by the linker script points to it. When we have something like GOTOFF relocs, we can use a plain reference to find the runtime address. Without that, we have to rely on the `l_addr' value, which is not the value we want when prelinked. */ -#ifdef DONT_USE_BOOTSTRAP_MAP - ehdr = (ElfW(Ehdr) *) &_begin; -#else - ehdr = (ElfW(Ehdr) *) bootstrap_map.l_addr; -#endif - phdr = (ElfW(Phdr) *) ((ElfW(Addr)) ehdr + ehdr->e_phoff); - for (cnt = 0; cnt < ehdr->e_phnum; ++cnt) + ElfW(Ehdr) *ehdr +# ifdef DONT_USE_BOOTSTRAP_MAP + = (ElfW(Ehdr) *) &_begin; +# else + = (ElfW(Ehdr) *) bootstrap_map.l_addr; +# endif + ElfW(Phdr) *phdr = (ElfW(Phdr) *) ((void *) ehdr + ehdr->e_phoff); + size_t cnt = ehdr->e_phnum; /* PT_TLS is usually the last phdr. */ + while (cnt-- > 0) if (phdr[cnt].p_type == PT_TLS) { void *tlsblock; @@ -431,13 +417,11 @@ _dl_start (void *arg) /* So far this is module number one. */ bootstrap_map.l_tls_modid = 1; - /* The TP got initialized. */ - bootstrap_map.l_tls_tp_initialized = 1; /* There can only be one PT_TLS entry. */ break; } -#endif /* use TLS */ +#endif /* USE___THREAD */ #ifdef ELF_MACHINE_BEFORE_RTLD_RELOC ELF_MACHINE_BEFORE_RTLD_RELOC (bootstrap_map.l_info); @@ -576,6 +560,15 @@ match_version (const char *string, struct link_map *map) return 0; } +/* _dl_error_catch_tsd points to this for the single-threaded case. + It's reset by the thread library for multithreaded programs. */ +static void ** __attribute__ ((const)) +startup_error_tsd (void) +{ + static void *data; + return &data; +} + static const char *library_path; /* The library search path. */ static const char *preloadlist; /* The list preloaded objects. */ static int version_info; /* Nonzero if information about @@ -605,6 +598,9 @@ dl_main (const ElfW(Phdr) *phdr, void *tcbp; #endif + /* Explicit initialization since the reloc would just be more work. */ + GL(dl_error_catch_tsd) = &startup_error_tsd; + /* Process the environment variable which control the behaviour. */ process_envvars (&mode); @@ -1564,16 +1560,9 @@ cannot allocate TLS data structures for initial thread"); into the main thread's TLS area, which we allocated above. */ _dl_allocate_tls_init (tcbp); - /* And finally install it for the main thread. */ -# ifndef HAVE___THREAD - TLS_INIT_TP (tcbp, GL(dl_rtld_map).l_tls_tp_initialized); -# else - /* If the compiler supports the __thread keyword we know that - at least ld.so itself uses TLS and therefore the thread - pointer was initialized earlier. */ - assert (GL(dl_rtld_map).l_tls_tp_initialized != 0); - TLS_INIT_TP (tcbp, 1); -# endif + /* And finally install it for the main thread. If ld.so itself uses + TLS we know the thread pointer was initialized earlier. */ + TLS_INIT_TP (tcbp, USE___THREAD); } #endif -- cgit v1.2.3