[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[commits] r13043 - in /fsf/trunk/ports: ./ sysdeps/arm/ sysdeps/arm/bits/



Author: eglibc
Date: Sat Mar  5 00:03:46 2011
New Revision: 13043

Log:
Import glibc-ports-mainline for 2011-03-05

Added:
    fsf/trunk/ports/sysdeps/arm/Makefile   (with props)
    fsf/trunk/ports/sysdeps/arm/dl-lookupcfg.h
    fsf/trunk/ports/sysdeps/arm/dl-tlsdesc.S
    fsf/trunk/ports/sysdeps/arm/dl-tlsdesc.h
    fsf/trunk/ports/sysdeps/arm/tlsdesc.c
    fsf/trunk/ports/sysdeps/arm/tlsdesc.sym
Modified:
    fsf/trunk/ports/ChangeLog.arm
    fsf/trunk/ports/sysdeps/arm/bits/linkmap.h
    fsf/trunk/ports/sysdeps/arm/dl-machine.h
    fsf/trunk/ports/sysdeps/arm/dl-tls.h

Modified: fsf/trunk/ports/ChangeLog.arm
==============================================================================
--- fsf/trunk/ports/ChangeLog.arm (original)
+++ fsf/trunk/ports/ChangeLog.arm Sat Mar  5 00:03:46 2011
@@ -1,3 +1,23 @@
+2011-03-05  Nathan Sidwell  <nathan@xxxxxxxxxxxxxxxx>
+	    Glauber de Oliveira Costa  <glommer@xxxxxxxxx>
+
+	* sysdeps/arm/dl-tlsdesc.h: New.
+	* sysdeps/arm/dl-tls.h (struct dl_tls_index): Make non-anonymous.
+	* sysdeps/arm/Makefile: Add tlsdesc, dl-tlsdesc for elf
+	subdirectory.
+	* sysdeps/arm/tlsdesc.c: New.
+	* sysdeps/arm/dl-machine.h: #include sysdeps and dl-tlsdesc.h.
+	(elf_machine_runtime_setup): Record dl_tlsdesc_lazy_resolver
+	address.
+	(elf_machine_type_class): Check R_ARM_TLS_DESC.
+	(elf_machine_rel): Add R_ARM_TLS_DESC case.
+	(elf_machine_lazy_rel): Likewise.
+	* sysdeps/arm/dl-tlsdesc.S: New.
+	* sysdeps/arm/bits/linkmap.h (struct link_map_machine): Add
+	tlsdesc_table field.
+	* sysdeps/arm/tlsdesc.sym: New.
+	* sysdeps/arm/dl-lookupcfg.h: New.
+
 2011-02-16  Manjunath Matti  <manjunath81@xxxxxxxxx>
 
 	* sysdeps/arm/sysdep.h (CALL_MCOUNT): Use __gnu_mcount_nc

Added: fsf/trunk/ports/sysdeps/arm/Makefile
==============================================================================
Binary file - no diff available.

Propchange: fsf/trunk/ports/sysdeps/arm/Makefile
------------------------------------------------------------------------------
    svn:mime-type = audio/x-669-mod

Modified: fsf/trunk/ports/sysdeps/arm/bits/linkmap.h
==============================================================================
--- fsf/trunk/ports/sysdeps/arm/bits/linkmap.h (original)
+++ fsf/trunk/ports/sysdeps/arm/bits/linkmap.h Sat Mar  5 00:03:46 2011
@@ -1,4 +1,5 @@
 struct link_map_machine
   {
     Elf32_Addr plt; /* Address of .plt */
+    void *tlsdesc_table; /* Address of TLS descriptor hash table.  */
   };

Added: fsf/trunk/ports/sysdeps/arm/dl-lookupcfg.h
==============================================================================
--- fsf/trunk/ports/sysdeps/arm/dl-lookupcfg.h (added)
+++ fsf/trunk/ports/sysdeps/arm/dl-lookupcfg.h Sat Mar  5 00:03:46 2011
@@ -1,0 +1,28 @@
+/* Configuration of lookup functions.
+   Copyright (C) 2006, 2010 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.  */
+
+#define DL_UNMAP_IS_SPECIAL
+
+#include_next <dl-lookupcfg.h>
+
+struct link_map;
+
+extern void internal_function _dl_unmap (struct link_map *map);
+
+#define DL_UNMAP(map) _dl_unmap (map)

Modified: fsf/trunk/ports/sysdeps/arm/dl-machine.h
==============================================================================
--- fsf/trunk/ports/sysdeps/arm/dl-machine.h (original)
+++ fsf/trunk/ports/sysdeps/arm/dl-machine.h Sat Mar  5 00:03:46 2011
@@ -25,6 +25,7 @@
 
 #include <sys/param.h>
 #include <tls.h>
+#include <dl-tlsdesc.h>
 
 #define CLEAR_CACHE(BEG,END)						\
   INTERNAL_SYSCALL_ARM (cacheflush, , 3, (BEG), (END), 0)
@@ -127,6 +128,11 @@
 	   the offset on the stack, and then jump to the resolved address.  */
 	got[2] = (Elf32_Addr) &_dl_runtime_resolve;
     }
+
+  if (l->l_info[ADDRIDX (DT_TLSDESC_GOT)] && lazy)
+    *(Elf32_Addr*)(D_PTR (l, l_info[ADDRIDX (DT_TLSDESC_GOT)]) + l->l_addr)
+      = (Elf32_Addr) &_dl_tlsdesc_lazy_resolver;
+
   return lazy;
 }
 
@@ -239,7 +245,8 @@
 #if defined USE_TLS && (!defined RTLD_BOOTSTRAP || USE___THREAD)
 # define elf_machine_type_class(type) \
   ((((type) == R_ARM_JUMP_SLOT || (type) == R_ARM_TLS_DTPMOD32		\
-     || (type) == R_ARM_TLS_DTPOFF32 || (type) == R_ARM_TLS_TPOFF32)	\
+     || (type) == R_ARM_TLS_DTPOFF32 || (type) == R_ARM_TLS_TPOFF32	\
+     || (type) == R_ARM_TLS_DESC)					\
     * ELF_RTYPE_CLASS_PLT)						\
    | (((type) == R_ARM_COPY) * ELF_RTYPE_CLASS_COPY))
 #else
@@ -421,6 +428,39 @@
 	    *reloc_addr += value;
 	    break;
 	  }
+	case R_ARM_TLS_DESC:
+	  {
+            struct tlsdesc volatile *td =
+	      (struct tlsdesc volatile *)reloc_addr;
+
+# ifndef RTLD_BOOTSTRAP
+	    if (! sym)
+	      td->entry = _dl_tlsdesc_undefweak;
+	    else
+# endif
+	      {
+		value = sym->st_value + td->argument.value;
+
+# ifndef RTLD_BOOTSTRAP
+#  ifndef SHARED
+		CHECK_STATIC_TLS (map, sym_map);
+#  else
+		if (!TRY_STATIC_TLS (map, sym_map))
+		  {
+		    td->argument.pointer
+		      = _dl_make_tlsdesc_dynamic (sym_map, value);
+		    td->entry = _dl_tlsdesc_dynamic;
+		  }
+		else
+#  endif
+# endif
+	        {
+		  td->argument.value = value + sym_map->l_tls_offset;
+		  td->entry = _dl_tlsdesc_return;
+	        }
+	      }
+	    }
+	    break;
 	case R_ARM_PC24:
 	  {
 	     Elf32_Sword addend;
@@ -612,6 +652,20 @@
       else
 	*reloc_addr = map->l_mach.plt;
     }
+#ifdef USE_TLS
+  else if (__builtin_expect (r_type == R_ARM_TLS_DESC, 1))
+    {
+      struct tlsdesc volatile *td =
+	(struct tlsdesc volatile *)reloc_addr;
+
+      /* The linker must have given us the parameter we need in the
+         first GOT entry, and left the second one empty. We fill the
+         last with the resolver address */
+      assert (td->entry == 0);
+      td->entry = (void*)(D_PTR (map, l_info[ADDRIDX (DT_TLSDESC_PLT)])
+			  + map->l_addr);
+    }
+#endif
   else
     _dl_reloc_bad_type (map, r_type, 1);
 }

Modified: fsf/trunk/ports/sysdeps/arm/dl-tls.h
==============================================================================
--- fsf/trunk/ports/sysdeps/arm/dl-tls.h (original)
+++ fsf/trunk/ports/sysdeps/arm/dl-tls.h Sat Mar  5 00:03:46 2011
@@ -19,7 +19,7 @@
 
 
 /* Type used for the representation of TLS information in the GOT.  */
-typedef struct
+typedef struct dl_tls_index
 {
   unsigned long int ti_module;
   unsigned long int ti_offset;

Added: fsf/trunk/ports/sysdeps/arm/dl-tlsdesc.S
==============================================================================
--- fsf/trunk/ports/sysdeps/arm/dl-tlsdesc.S (added)
+++ fsf/trunk/ports/sysdeps/arm/dl-tlsdesc.S Sat Mar  5 00:03:46 2011
@@ -1,0 +1,222 @@
+/* Thread-local storage handling in the ELF dynamic linker.  ARM version.
+   Copyright (C) 2006, 2010 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 <sysdep.h>
+#include <tls.h>
+#include "tlsdesc.h"
+
+#ifdef __USE_BX__
+  #define BX(x)	bx x
+#else
+  #define BX(x)	mov pc, x
+#endif
+
+	.text
+	@ emit debug information with cfi
+	@ use arm-specific pseudos for unwinding itself
+	.cfi_sections .debug_frame
+#ifdef USE_TLS
+	.hidden _dl_tlsdesc_return
+	.global	_dl_tlsdesc_return
+	.type	_dl_tlsdesc_return,#function
+	cfi_startproc
+	.fnstart
+	.align 2
+_dl_tlsdesc_return:
+	ldr	r0, [r0]
+	BX	(lr)
+	.fnend
+	cfi_endproc
+	.size	_dl_tlsdesc_return, .-_dl_tlsdesc_return
+
+	.hidden _dl_tlsdesc_undefweak
+	.global	_dl_tlsdesc_undefweak
+	.type	_dl_tlsdesc_undefweak,#function
+	cfi_startproc
+	.fnstart
+	.align 2
+_dl_tlsdesc_undefweak:
+	@ Are we allowed a misaligned stack pointer calling read_tp?
+	.save	{lr}
+	stmdb 	sp!, {lr}
+	cfi_adjust_cfa_offset (4)
+	cfi_rel_offset (lr,0)
+	bl 	__aeabi_read_tp
+	rsb 	r0, r0, #0
+	ldmia 	sp!, {lr}
+	cfi_adjust_cfa_offset (-4)
+	cfi_restore (lr)
+	BX	(lr)
+
+	cfi_endproc
+	.fnend
+	.size	_dl_tlsdesc_undefweak, .-_dl_tlsdesc_undefweak
+
+#ifdef SHARED
+	.hidden _dl_tlsdesc_dynamic
+	.global	_dl_tlsdesc_dynamic
+	.type	_dl_tlsdesc_dynamic,#function
+
+
+/*
+	The assembly code that follows is a rendition of the following
+	C code, hand-optimized a little bit.
+
+ptrdiff_t
+_dl_tlsdesc_dynamic(struct tlsdesc *tdp)
+{
+       struct tlsdesc_dynamic_arg *td = tdp->argument.pointer;
+       dtv_t *dtv = (dtv_t *)THREAD_DTV();
+       if (__builtin_expect (td->gen_count <= dtv[0].counter
+                             && dtv[td->tlsinfo.ti_module].pointer.val
+                                != TLS_DTV_UNALLOCATED,
+                             1))
+               return dtv[td->tlsinfo.ti_module].pointer.val +
+                       td->tlsinfo.ti_offset - __builtin_thread_pointer();
+
+       return __tls_get_addr (&td->tlsinfo) - __builtin_thread_pointer();
+}
+
+*/
+	cfi_startproc
+	.fnstart
+	.align 2
+_dl_tlsdesc_dynamic:
+	/* Our calling convention is to clobber r0, r1 and the processor
+	   flags.  All others that are modified must be saved */
+	.save	{r2,r3,r4,lr}
+	stmdb   sp!, {r2,r3,r4,lr}
+	cfi_adjust_cfa_offset (16)
+	cfi_rel_offset (r2,0)
+	cfi_rel_offset (r3,4)
+	cfi_rel_offset (r4,8)
+	cfi_rel_offset (lr,12)
+	ldr	r1, [r0] /* td */
+	bl	__aeabi_read_tp
+	mov	r4, r0 /* r4 = tp */
+	ldr	r0, [r0]
+	ldr	r2, [r1, #8] /* gen_count */
+	ldr	r3, [r0]
+	cmp	r2, r3
+	bhi	1f
+	ldr	r3, [r1]
+	ldr	r2, [r0, r3, lsl #3]
+	cmn	r2, #1
+	ldrne	r3, [r1, #4]
+	addne	r3, r2, r3
+	rsbne	r0, r4, r3
+	bne	2f
+1:	mov	r0, r1
+	bl	__tls_get_addr
+	rsb	r0, r4, r0
+2:	ldmia	sp!, {r2,r3,r4, lr}
+	cfi_adjust_cfa_offset (-16)
+	cfi_restore (lr)
+	cfi_restore (r4)
+	cfi_restore (r3)
+	cfi_restore (r2)
+	BX      (lr)
+	.fnend
+	cfi_endproc
+	.size	_dl_tlsdesc_dynamic, .-_dl_tlsdesc_dynamic
+#endif /* SHARED */
+
+/* lazy resolved for tls descriptors.  */
+	.hidden _dl_tlsdesc_lazy_resolver
+	.global	_dl_tlsdesc_lazy_resolver
+	.type	_dl_tlsdesc_lazy_resolver,#function
+	cfi_startproc
+	.fnstart
+	.align 2
+_dl_tlsdesc_lazy_resolver:
+	/* r0 points at the tlsdesc,
+	   r1 points at the GOT
+	   r2 was pushed by the trampoline and used as a temp,
+	      we need to pop it here.
+	  We push the remaining call-clobbered registers here, and also
+	  R1 -- to keep the stack correctly aligned.  */
+	/* Tell the unwinder that r2 has already been pushed.  */
+	.save	{r2}
+	cfi_adjust_cfa_offset (4)
+	cfi_rel_offset (r2, 0)
+	.save	{r0,r1,r3,ip,lr}
+	stmdb	sp!, {r0, r1, r3, ip, lr}
+	cfi_adjust_cfa_offset (20)
+	cfi_rel_offset (r0, 0)
+	cfi_rel_offset (r1, 4)
+	cfi_rel_offset (r3, 8)
+	cfi_rel_offset (ip, 12)
+	cfi_rel_offset (lr, 16)
+	bl	_dl_tlsdesc_lazy_resolver_fixup
+	ldmia	sp!, {r0, r1, r3, ip, lr}
+	cfi_adjust_cfa_offset (-20)
+	cfi_restore (lr)
+	cfi_restore (ip)
+	cfi_restore (r3)
+	cfi_restore (r1)
+	cfi_restore (r0)
+	ldmia	sp!, {r2}
+	cfi_adjust_cfa_offset (-4)
+	cfi_restore (r2)
+	ldr	r1, [r0, #4]
+	BX	(r1)
+	.fnend
+	cfi_endproc
+	.size	_dl_tlsdesc_lazy_resolver, .-_dl_tlsdesc_lazy_resolver
+
+/* Holder for lazy tls descriptors being resolve in another thread.
+   Same ABI as the lazy resolver itself.  */
+	.hidden _dl_tlsdesc_resolve_hold
+	.global	_dl_tlsdesc_resolve_hold
+	.type	_dl_tlsdesc_resolve_hold,#function
+	cfi_startproc
+	.fnstart
+	.align 2
+_dl_tlsdesc_resolve_hold:
+	/* Tell the unwinder that r2 has already been pushed.  */
+	.save	{r2}
+	cfi_adjust_cfa_offset (4)
+	cfi_rel_offset (r2, 0)
+	.save	{r0,r1,r3,ip,lr}
+	stmdb   sp!, {r0, r1, r3, ip, lr}
+	cfi_adjust_cfa_offset (20)
+	cfi_rel_offset (r0, 0)
+	cfi_rel_offset (r1, 4)
+	cfi_rel_offset (r3, 8)
+	cfi_rel_offset (ip, 12)
+	cfi_rel_offset (lr, 16)
+	adr	r2, _dl_tlsdesc_resolve_hold
+	bl	_dl_tlsdesc_resolve_hold_fixup
+	ldmia   sp!, {r0, r1, r3, ip, lr}
+	cfi_adjust_cfa_offset (-20)
+	cfi_restore (lr)
+	cfi_restore (ip)
+	cfi_restore (r3)
+	cfi_restore (r1)
+	cfi_restore (r0)
+	ldmia   sp!, {r2}
+	cfi_adjust_cfa_offset (-4)
+	cfi_restore (r2)
+	ldr     r1, [r0, #4]
+	BX      (r1)
+	.fnend
+	cfi_endproc
+	.size	_dl_tlsdesc_resolve_hold, .-_dl_tlsdesc_resolve_hold
+
+#endif /* USE_TLS */

Added: fsf/trunk/ports/sysdeps/arm/dl-tlsdesc.h
==============================================================================
--- fsf/trunk/ports/sysdeps/arm/dl-tlsdesc.h (added)
+++ fsf/trunk/ports/sysdeps/arm/dl-tlsdesc.h Sat Mar  5 00:03:46 2011
@@ -1,0 +1,69 @@
+/* Thread-local storage descriptor handling in the ELF dynamic linker.
+   ARM version.
+   Copyright (C) 2005, 2010 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; witout 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.  */
+
+#ifndef _ARM_DL_TLSDESC_H
+# define _ARM_DL_TLSDESC_H 1
+
+/* Use this to access DT_TLSDESC_PLT and DT_TLSDESC_GOT.  */
+#ifndef ADDRIDX
+# define ADDRIDX(tag) (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGNUM \
+		       + DT_EXTRANUM + DT_VALNUM + DT_ADDRTAGIDX (tag))
+#endif
+
+/* Type used to represent a TLS descriptor in the GOT.  */
+struct tlsdesc
+{
+  union
+    {
+      void *pointer;
+      long value;
+    } argument;
+  ptrdiff_t (*entry)(struct tlsdesc *);
+};
+
+
+typedef struct dl_tls_index
+{
+  unsigned long int ti_module;
+  unsigned long int ti_offset;
+} tls_index;
+
+/* Type used as the argument in a TLS descriptor for a symbol that
+   needs dynamic TLS offsets.  */
+struct tlsdesc_dynamic_arg
+{
+  tls_index tlsinfo;
+  size_t gen_count;
+};
+
+extern ptrdiff_t attribute_hidden
+  _dl_tlsdesc_return(struct tlsdesc *),
+  _dl_tlsdesc_undefweak(struct tlsdesc *),
+  _dl_tlsdesc_resolve_hold(struct tlsdesc *),
+  _dl_tlsdesc_lazy_resolver(struct tlsdesc *);
+
+# ifdef SHARED
+extern void *_dl_make_tlsdesc_dynamic (struct link_map *map, size_t ti_offset);
+
+extern ptrdiff_t attribute_hidden
+  _dl_tlsdesc_dynamic(struct tlsdesc *);
+# endif
+
+#endif

Added: fsf/trunk/ports/sysdeps/arm/tlsdesc.c
==============================================================================
--- fsf/trunk/ports/sysdeps/arm/tlsdesc.c (added)
+++ fsf/trunk/ports/sysdeps/arm/tlsdesc.c Sat Mar  5 00:03:46 2011
@@ -1,0 +1,164 @@
+/* Manage TLS descriptors.  ARM version.
+   Copyright (C) 2005, 2010 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 <link.h>
+#include <ldsodefs.h>
+#include <elf/dynamic-link.h>
+#include <tls.h>
+#include <dl-tlsdesc.h>
+#include <tlsdeschtab.h>
+
+#ifdef USE_TLS
+
+/* This function is used to lazily resolve TLS_DESC REL relocations
+   Besides the TLS descriptor itself, we get the module's got address
+   as the second parameter. */
+
+void
+attribute_hidden
+_dl_tlsdesc_lazy_resolver_fixup (struct tlsdesc volatile *td,
+				 Elf32_Addr *got)
+{
+  struct link_map *l = (struct link_map *)got[1];
+  lookup_t result;
+  unsigned long value;
+
+  if (_dl_tlsdesc_resolve_early_return_p
+      (td, (void*)(D_PTR (l, l_info[ADDRIDX (DT_TLSDESC_PLT)]) + l->l_addr)))
+    return;
+
+  if (td->argument.value & 0x80000000)
+    {
+      /* A global symbol, this is the symbol index.  */
+      /* The code below was borrowed from _dl_fixup().  */
+      const Elf_Symndx symndx = td->argument.value ^ 0x80000000;
+      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 ElfW(Sym) *sym = &symtab[symndx];
+
+      /* Look up the target symbol.  If the normal lookup rules are not
+	 used don't look in the global scope.  */
+      if (ELFW(ST_BIND) (sym->st_info) != STB_LOCAL
+	  && __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[symndx] & 0x7fff;
+	      version = &l->l_versions[ndx];
+	      if (version->hash == 0)
+		version = NULL;
+	    }
+
+	  result = _dl_lookup_symbol_x
+	    (strtab + sym->st_name, l, &sym,
+	     l->l_scope, version, ELF_RTYPE_CLASS_PLT,
+	     DL_LOOKUP_ADD_DEPENDENCY, NULL);
+	  if (sym)
+	    value = sym->st_value;
+	  else
+	    {
+	      td->entry = _dl_tlsdesc_undefweak;
+	      goto done;
+	    }
+	}
+      else
+	{
+	  /* We already found the symbol.  The module (and therefore its load
+	     address) is also known.  */
+	  result = l;
+	  value = sym->st_value;
+	}
+    }
+  else
+    {
+      /* A local symbol, this is the offset within our tls section.
+	 */
+      value = td->argument.value;
+      result = l;
+    }
+
+#ifndef SHARED
+  CHECK_STATIC_TLS (l, result);
+#else
+  if (!TRY_STATIC_TLS (l, result))
+    {
+      td->argument.pointer = _dl_make_tlsdesc_dynamic (result, value);
+      td->entry = _dl_tlsdesc_dynamic;
+    }
+  else
+#endif
+    {
+      td->argument.value = value + result->l_tls_offset;
+      td->entry = _dl_tlsdesc_return;
+    }
+
+ done:
+  _dl_tlsdesc_wake_up_held_fixups ();
+}
+
+/* This function is used to avoid busy waiting for other threads to
+   complete the lazy relocation.  Once another thread wins the race to
+   relocate a TLS descriptor, it sets the descriptor up such that this
+   function is called to wait until the resolver releases the
+   lock.  */
+
+void
+attribute_hidden
+_dl_tlsdesc_resolve_hold_fixup (struct tlsdesc volatile *td,
+				void *caller)
+{
+  /* Maybe we're lucky and can return early.  */
+  if (caller != td->entry)
+    return;
+
+  /* Locking here will stop execution until the running resolver runs
+     _dl_tlsdesc_wake_up_held_fixups(), releasing the lock.
+
+     FIXME: We'd be better off waiting on a condition variable, such
+     that we didn't have to hold the lock throughout the relocation
+     processing.  */
+  __rtld_lock_lock_recursive (GL(dl_load_lock));
+  __rtld_lock_unlock_recursive (GL(dl_load_lock));
+}
+
+/* Unmap the dynamic object, but also release its TLS descriptor table
+   if there is one.  */
+
+void
+internal_function
+_dl_unmap (struct link_map *map)
+{
+  __munmap ((void *) (map)->l_map_start,
+	    (map)->l_map_end - (map)->l_map_start);
+
+#if SHARED
+  /* _dl_unmap is only called for dlopen()ed libraries, for which
+     calling free() is safe, or before we've completed the initial
+     relocation, in which case calling free() is probably pointless,
+     but still safe.  */
+  if (map->l_mach.tlsdesc_table)
+    htab_delete (map->l_mach.tlsdesc_table);
+#endif
+}
+#endif

Added: fsf/trunk/ports/sysdeps/arm/tlsdesc.sym
==============================================================================
--- fsf/trunk/ports/sysdeps/arm/tlsdesc.sym (added)
+++ fsf/trunk/ports/sysdeps/arm/tlsdesc.sym Sat Mar  5 00:03:46 2011
@@ -1,0 +1,19 @@
+#include <stddef.h>
+#include <sysdep.h>
+#include <tls.h>
+#include <link.h>
+#include <dl-tlsdesc.h>
+
+--
+
+-- Abuse tls.h macros to derive offsets relative to the thread register.
+#if defined USE_TLS
+
+
+TLSDESC_ARG			offsetof(struct tlsdesc, argument.pointer)
+
+TLSDESC_GEN_COUNT		offsetof(struct tlsdesc_dynamic_arg, gen_count)
+TLSDESC_MODID			offsetof(struct tlsdesc_dynamic_arg, tlsinfo.ti_module)
+TLSDESC_MODOFF			offsetof(struct tlsdesc_dynamic_arg, tlsinfo.ti_offset)
+
+#endif