[PATCH] ldso: auto disable lazy relocation for some fdpic ports when using threads

Mike Frysinger vapier at gentoo.org
Tue Feb 22 02:27:18 UTC 2011


From: Bernd Schmidt <bernds_cb1 at t-online.de>

The fdpic code requires two 32bit values to be read/written atomically
(one pointer for the GOT and one for the PLT).  FRV has an insn to do
this sort of thing, but Blackfin does not.  So in order to use FDPIC on
a threaded system, we need to disable lazy relocation.

Rather than disable it for all applications (non-threaded included),
take a middle ground.  When the ldso detects loading of the libpthread
library, automatically turn off lazy relocation.  This isn't a perfect
fix as it doesn't detect when someone calls clone() manually, but in
practice, it works for every realistic case.  For the 1 person in the
world doing weird stuff, they can build with -Wl,-z,now themselves.

Signed-off-by: Bernd Schmidt <bernds_cb1 at t-online.de>
Signed-off-by: Mike Frysinger <vapier at gentoo.org>
---
 Rules.mak                                          |    1 +
 ldso/ldso/Makefile.in                              |    2 +-
 ldso/ldso/ldso.c                                   |   16 +++++++++++++++-
 .../sysdeps/linux/bfin/bits/uClibc_arch_features.h |    3 +++
 libc/sysdeps/linux/frv/bits/uClibc_arch_features.h |    3 +++
 5 files changed, 23 insertions(+), 2 deletions(-)

diff --git a/Rules.mak b/Rules.mak
index 8165cca..f23f159 100644
--- a/Rules.mak
+++ b/Rules.mak
@@ -136,6 +136,7 @@ endif
 ifneq ($(HAS_NO_THREADS),y)
 libpthread.depend := $(top_builddir)lib/libpthread.so
 endif
+UCLIBC_LIBPTHREAD = libpthread.so.$(ABI_VERSION)
 interp := $(top_builddir)lib/interp.os
 ldso := $(top_builddir)lib/$(UCLIBC_LDSO)
 headers_dep := $(top_builddir)include/bits/sysnum.h
diff --git a/ldso/ldso/Makefile.in b/ldso/ldso/Makefile.in
index e71ae15..2a5a81b 100644
--- a/ldso/ldso/Makefile.in
+++ b/ldso/ldso/Makefile.in
@@ -13,7 +13,7 @@ CFLAGS-ldso := -DNOT_IN_libc -DIS_IN_rtld $(SSP_DISABLE_FLAGS)
 CFLAGS-ldso += -fno-omit-frame-pointer
 
 CFLAGS-ldso += -I$(top_srcdir)ldso/ldso/$(TARGET_ARCH) -I$(top_srcdir)ldso/include -I$(top_srcdir)ldso/ldso
-CFLAGS-ldso += -DUCLIBC_RUNTIME_PREFIX=\"$(RUNTIME_PREFIX)\" -DUCLIBC_LDSO=\"$(UCLIBC_LDSO)\"
+CFLAGS-ldso += -DUCLIBC_RUNTIME_PREFIX=\"$(RUNTIME_PREFIX)\" -DUCLIBC_LDSO=\"$(UCLIBC_LDSO)\" -DUCLIBC_LIBPTHREAD=\"$(UCLIBC_LIBPTHREAD)\"
 
 ifeq ($(DODEBUG),y)
 # Not really much point in including debugging info, since gdb
diff --git a/ldso/ldso/ldso.c b/ldso/ldso/ldso.c
index ea4ad0f..5bcdfec 100644
--- a/ldso/ldso/ldso.c
+++ b/ldso/ldso/ldso.c
@@ -284,7 +284,7 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr,
 	ElfW(Dyn) *dpnt;
 	char *lpntstr;
 	unsigned int i;
-	int unlazy = 0, trace_loaded_objects = 0;
+	int unlazy = 0, must_unlazy = 0, trace_loaded_objects = 0;
 	struct dyn_elf *rpnt;
 	struct elf_resolve *tcurr;
 	struct elf_resolve *tpnt1;
@@ -777,6 +777,15 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr,
 				name = _dl_get_last_path_component(lpntstr);
 				if (_dl_strcmp(name, UCLIBC_LDSO) == 0)
 					continue;
+#if !defined(__UCLIBC_HAVE_64BIT_LDST__) && defined(__FDPIC__)
+				/* An FDPIC entry consists of two 32bit values -- a GOT
+				   pointer and a PLT pointer.  In order to be thread safe,
+				   the ldso has to read/write those entries atomically.
+				   But if the arch cannot load/store 64bits in one go,
+				   we cannot safely do lazy relocation.  */
+				if (_dl_strcmp(name, UCLIBC_LIBPTHREAD) == 0)
+					must_unlazy = 1;
+#endif
 
 				_dl_if_debug_dprint("\tfile='%s';  needed by '%s'\n", lpntstr, _dl_progname);
 
@@ -815,6 +824,11 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr,
 	}
 	_dl_unmap_cache();
 
+	if (must_unlazy)
+		for (tcurr = _dl_loaded_modules; tcurr; tcurr = tcurr->next) {
+			tcurr->rtld_flags |= RTLD_NOW;
+		}
+
 	--nlist; /* Exclude the application. */
 	init_fini_list = _dl_malloc(nlist * sizeof(struct elf_resolve *));
 	i = 0;
diff --git a/libc/sysdeps/linux/bfin/bits/uClibc_arch_features.h b/libc/sysdeps/linux/bfin/bits/uClibc_arch_features.h
index 4bab547..90abc45 100644
--- a/libc/sysdeps/linux/bfin/bits/uClibc_arch_features.h
+++ b/libc/sysdeps/linux/bfin/bits/uClibc_arch_features.h
@@ -45,4 +45,7 @@
 /* only weird assemblers generally need this */
 #undef __UCLIBC_ASM_LINE_SEP__
 
+/* does your target have atomic 64bit loads/stores ? */
+#undef __UCLIBC_HAVE_ATOMIC_64_LDST__
+
 #endif /* _BITS_UCLIBC_ARCH_FEATURES_H */
diff --git a/libc/sysdeps/linux/frv/bits/uClibc_arch_features.h b/libc/sysdeps/linux/frv/bits/uClibc_arch_features.h
index 2a9422e..edb2c68 100644
--- a/libc/sysdeps/linux/frv/bits/uClibc_arch_features.h
+++ b/libc/sysdeps/linux/frv/bits/uClibc_arch_features.h
@@ -45,4 +45,7 @@
 /* only weird assemblers generally need this */
 #undef __UCLIBC_ASM_LINE_SEP__
 
+/* does your target have atomic 64bit loads/stores ? */
+#define __UCLIBC_HAVE_ATOMIC_64_LDST__
+
 #endif /* _BITS_UCLIBC_ARCH_FEATURES_H */
-- 
1.7.4.1



More information about the uClibc mailing list