[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[commits] r13043 - in /fsf/trunk/ports: ./ sysdeps/arm/ sysdeps/arm/bits/
- To: commits@xxxxxxxxxx
- Subject: [commits] r13043 - in /fsf/trunk/ports: ./ sysdeps/arm/ sysdeps/arm/bits/
- From: eglibc@xxxxxxxxxx
- Date: Sat, 05 Mar 2011 08:03:47 -0000
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