From 3447f0d785a18f1fc8efefefb0d22bd917044379 Mon Sep 17 00:00:00 2001 From: Nathan Sidwell Date: Sat, 5 Mar 2011 03:39:15 +0000 Subject: [PATCH] ARM TLS descriptors support. --- ChangeLog.arm | 20 ++++ sysdeps/arm/Makefile | 9 ++ sysdeps/arm/bits/linkmap.h | 1 + sysdeps/arm/dl-lookupcfg.h | 28 ++++++ sysdeps/arm/dl-machine.h | 56 +++++++++++- sysdeps/arm/dl-tls.h | 2 +- sysdeps/arm/dl-tlsdesc.S | 222 +++++++++++++++++++++++++++++++++++++++++++++ sysdeps/arm/dl-tlsdesc.h | 69 ++++++++++++++ sysdeps/arm/tlsdesc.c | 164 +++++++++++++++++++++++++++++++++ sysdeps/arm/tlsdesc.sym | 19 ++++ 10 files changed, 588 insertions(+), 2 deletions(-) create mode 100644 sysdeps/arm/Makefile create mode 100644 sysdeps/arm/dl-lookupcfg.h create mode 100644 sysdeps/arm/dl-tlsdesc.S create mode 100644 sysdeps/arm/dl-tlsdesc.h create mode 100644 sysdeps/arm/tlsdesc.c create mode 100644 sysdeps/arm/tlsdesc.sym diff --git a/ChangeLog.arm b/ChangeLog.arm index 5e59f09..1e05d41 100644 --- a/ChangeLog.arm +++ b/ChangeLog.arm @@ -1,3 +1,23 @@ +2011-03-05 Nathan Sidwell + Glauber de Oliveira Costa + + * 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 * sysdeps/arm/sysdep.h (CALL_MCOUNT): Use __gnu_mcount_nc diff --git a/sysdeps/arm/Makefile b/sysdeps/arm/Makefile new file mode 100644 index 0000000..5651161 --- /dev/null +++ b/sysdeps/arm/Makefile @@ -0,0 +1,9 @@ +ifeq ($(subdir),elf) +sysdep-dl-routines += tlsdesc dl-tlsdesc +sysdep_routines += tlsdesc dl-tlsdesc +sysdep-rtld-routines += tlsdesc dl-tlsdesc +endif + +ifeq ($(subdir),csu) +gen-as-const-headers += tlsdesc.sym +endif diff --git a/sysdeps/arm/bits/linkmap.h b/sysdeps/arm/bits/linkmap.h index 648976d..7c2b4a6 100644 --- a/sysdeps/arm/bits/linkmap.h +++ b/sysdeps/arm/bits/linkmap.h @@ -1,4 +1,5 @@ struct link_map_machine { Elf32_Addr plt; /* Address of .plt */ + void *tlsdesc_table; /* Address of TLS descriptor hash table. */ }; diff --git a/sysdeps/arm/dl-lookupcfg.h b/sysdeps/arm/dl-lookupcfg.h new file mode 100644 index 0000000..29b2587 --- /dev/null +++ b/sysdeps/arm/dl-lookupcfg.h @@ -0,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 + +struct link_map; + +extern void internal_function _dl_unmap (struct link_map *map); + +#define DL_UNMAP(map) _dl_unmap (map) diff --git a/sysdeps/arm/dl-machine.h b/sysdeps/arm/dl-machine.h index c555763..9929f76 100644 --- a/sysdeps/arm/dl-machine.h +++ b/sysdeps/arm/dl-machine.h @@ -25,6 +25,7 @@ #include #include +#include #define CLEAR_CACHE(BEG,END) \ INTERNAL_SYSCALL_ARM (cacheflush, , 3, (BEG), (END), 0) @@ -127,6 +128,11 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile) 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 @@ _dl_start_user:\n\ #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 @@ elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc, *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 @@ elf_machine_lazy_rel (struct link_map *map, 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); } diff --git a/sysdeps/arm/dl-tls.h b/sysdeps/arm/dl-tls.h index e0324a7..02285a7 100644 --- a/sysdeps/arm/dl-tls.h +++ b/sysdeps/arm/dl-tls.h @@ -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; diff --git a/sysdeps/arm/dl-tlsdesc.S b/sysdeps/arm/dl-tlsdesc.S new file mode 100644 index 0000000..19e4ed3 --- /dev/null +++ b/sysdeps/arm/dl-tlsdesc.S @@ -0,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 +#include +#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 */ diff --git a/sysdeps/arm/dl-tlsdesc.h b/sysdeps/arm/dl-tlsdesc.h new file mode 100644 index 0000000..3817d7e --- /dev/null +++ b/sysdeps/arm/dl-tlsdesc.h @@ -0,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 diff --git a/sysdeps/arm/tlsdesc.c b/sysdeps/arm/tlsdesc.c new file mode 100644 index 0000000..e0b970f --- /dev/null +++ b/sysdeps/arm/tlsdesc.c @@ -0,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 +#include +#include +#include +#include +#include + +#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 diff --git a/sysdeps/arm/tlsdesc.sym b/sysdeps/arm/tlsdesc.sym new file mode 100644 index 0000000..a1deb21 --- /dev/null +++ b/sysdeps/arm/tlsdesc.sym @@ -0,0 +1,19 @@ +#include +#include +#include +#include +#include + +-- + +-- 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 -- 2.7.4