From: Bernd Schmidt <[email protected]>

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 <[email protected]>
Signed-off-by: Mike Frysinger <[email protected]>
---
 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

_______________________________________________
uClibc mailing list
[email protected]
http://lists.busybox.net/mailman/listinfo/uclibc

Reply via email to