about summary refs log tree commit diff
path: root/elf
diff options
context:
space:
mode:
Diffstat (limited to 'elf')
-rw-r--r--elf/Makefile8
-rw-r--r--elf/dl-close.c5
-rw-r--r--elf/tls-macros.h69
-rw-r--r--elf/tst-array4.c18
-rw-r--r--elf/tst-array4.exp19
5 files changed, 115 insertions, 4 deletions
diff --git a/elf/Makefile b/elf/Makefile
index c6320d8867..09ea94800d 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -121,7 +121,7 @@ endif
 
 tests = tst-tls1 tst-tls2 tst-tls9
 ifeq (yes,$(have-initfini-array))
-tests += tst-array1 tst-array2 tst-array3
+tests += tst-array1 tst-array2 tst-array3 tst-array4
 endif
 ifeq (yes,$(build-static))
 tests-static = tst-tls1-static tst-tls2-static
@@ -594,6 +594,12 @@ $(objpfx)tst-array3.out: $(objpfx)tst-array3
 	  $(objpfx)tst-array3 > $@
 	cmp $@ tst-array1.exp > /dev/null
 
+$(objpfx)tst-array4: $(libdl)
+$(objpfx)tst-array4.out: $(objpfx)tst-array4 $(objpfx)tst-array2dep.so
+	$(elf-objpfx)$(rtld-installed-name) \
+	  --library-path $(rpath-link)$(patsubst %,:%,$(sysdep-library-path)) \
+	  $< > $@
+	cmp $@ tst-array4.exp > /dev/null
 
 check-textrel-CFLAGS = -O
 $(objpfx)check-textrel: check-textrel.c
diff --git a/elf/dl-close.c b/elf/dl-close.c
index cdebc739e8..1d4a8c3653 100644
--- a/elf/dl-close.c
+++ b/elf/dl-close.c
@@ -238,10 +238,9 @@ _dl_close (void *_map)
 				    + 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)));
-		  unsigned int cnt;
 
-		  for (cnt = 0; cnt < sz; ++cnt)
-		    ((fini_t) (imap->l_addr + array[cnt])) ();
+		  while (sz-- > 0)
+		    ((fini_t) array[sz]) ();
 		}
 
 	      /* Next try the old-style destructor.  */
diff --git a/elf/tls-macros.h b/elf/tls-macros.h
index 046a7d4c92..2de4b1a1af 100644
--- a/elf/tls-macros.h
+++ b/elf/tls-macros.h
@@ -298,6 +298,75 @@ register void *__gp __asm__("$29");
           : "=r" (__l) : : "loc0", __TLS_CALL_CLOBBERS);		      \
      __l; })
 
+#elif defined __sparc__ && !defined __arch64__
+
+# define TLS_LE(x) \
+  ({ int *__l;								      \
+     asm ("sethi %%tle_hix22(" #x "), %0" : "=r" (__l));		      \
+     asm ("xor %1, %%tle_lox10(" #x "), %0" : "=r" (__l) : "r" (__l));	      \
+     asm ("add %%g7, %1, %0" : "=r" (__l) : "r" (__l));			      \
+     __l; })
+
+# ifdef __PIC__ 
+#  define TLS_LOAD_PIC \
+  ({ register long pc __asm__ ("%o7");					      \
+     long got;								      \
+     asm ("sethi %%hi(_GLOBAL_OFFSET_TABLE_-4), %1\n\t"			      \
+	  "call .+8\n\t"						      \
+	  "add %1, %%lo(_GLOBAL_OFFSET_TABLE_+4), %1\n\t"		      \
+	  "add %1, %0, %1\n\t"						      \
+	  : "=r" (pc), "=r" (got));					      \
+     got; })
+# else
+#  define TLS_LOAD_PIC \
+   ({ long got;								      \
+      asm (".hidden _GLOBAL_OFFSET_TABLE_\n\t"				      \
+	   "sethi %%hi(_GLOBAL_OFFSET_TABLE_), %0\n\t"			      \
+	   "or %0, %%lo(_GLOBAL_OFFSET_TABLE_), %0"			      \
+	   : "=r" (got));						      \
+      got; })
+# endif
+
+# define TLS_IE(x) \
+  ({ int *__l;								      \
+     asm ("sethi %%tie_hi22(" #x "), %0" : "=r" (__l));			      \
+     asm ("add %1, %%tie_lo10(" #x "), %0" : "=r" (__l) : "r" (__l));	      \
+     asm ("ld [%1 + %2], %0, %%tie_ld(" #x ")"				      \
+	  : "=r" (__l) : "r" (TLS_LOAD_PIC), "r" (__l));		      \
+     asm ("add %%g7, %1, %0, %%tie_add(" #x ")" : "=r" (__l) : "r" (__l));    \
+     __l; })
+
+# define TLS_LD(x) \
+  ({ int *__l; register void *__o0 asm ("%o0");				      \
+     long __o;								      \
+     asm ("sethi %%tldm_hi22(" #x "), %0" : "=r" (__l));		      \
+     asm ("add %1, %%tldm_lo10(" #x "), %0" : "=r" (__l) : "r" (__l));	      \
+     asm ("add %1, %2, %0, %%tldm_add(" #x ")"				      \
+	  : "=r" (__o0) : "r" (TLS_LOAD_PIC), "r" (__l));		      \
+     asm ("call __tls_get_addr, %%tgd_call(" #x ")\n\t"			      \
+	  " nop"							      \
+	  : "=r" (__o0) : "0" (__o0)					      \
+	  : "g1", "g2", "g3", "g4", "g5", "g6", "o1", "o2", "o3", "o4",	      \
+	    "o5", "o7");						      \
+     asm ("sethi %%tldo_hix22(" #x "), %0" : "=r" (__o));		      \
+     asm ("xor %1, %%tldo_lox10(" #x "), %0" : "=r" (__o) : "r" (__o));	      \
+     asm ("add %1, %2, %0, %%tldo_add(" #x ")" : "=r" (__l)		      \
+	  : "r" (__o0), "r" (__o));					      \
+     __l; })
+
+# define TLS_GD(x) \
+  ({ int *__l; register void *__o0 asm ("%o0");				      \
+     asm ("sethi %%tgd_hi22(" #x "), %0" : "=r" (__l));			      \
+     asm ("add %1, %%tgd_lo10(" #x "), %0" : "=r" (__l) : "r" (__l));	      \
+     asm ("add %1, %2, %0, %%tgd_add(" #x ")"				      \
+	  : "=r" (__o0) : "r" (TLS_LOAD_PIC), "r" (__l));		      \
+     asm ("call __tls_get_addr, %%tgd_call(" #x ")\n\t"			      \
+	  " nop"							      \
+	  : "=r" (__o0) : "0" (__o0)					      \
+	  : "g1", "g2", "g3", "g4", "g5", "g6", "o1", "o2", "o3", "o4",	      \
+	    "o5", "o7");						      \
+     __o0; })
+
 #else
 # error "No support for this architecture so far."
 #endif
diff --git a/elf/tst-array4.c b/elf/tst-array4.c
new file mode 100644
index 0000000000..ac3d4eb716
--- /dev/null
+++ b/elf/tst-array4.c
@@ -0,0 +1,18 @@
+#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
new file mode 100644
index 0000000000..560444d2e8
--- /dev/null
+++ b/elf/tst-array4.exp
@@ -0,0 +1,19 @@
+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