summaryrefslogtreecommitdiff
path: root/ldso
diff options
context:
space:
mode:
authorWaldemar Brodkorb <wbx@uclibc-ng.org>2017-12-16 21:01:39 +0100
committerWaldemar Brodkorb <wbx@uclibc-ng.org>2017-12-31 11:12:07 +0100
commit23bb649090ff588e8642f0c581cfe7ce2d29c757 (patch)
tree4a68d696415fce9f2dd50edf27a79bacbde3fc50 /ldso
parent604781391549faafc59516700d9439ab1a7ec19b (diff)
m68k: add NPTL/TLS support
Port over NPTL/TLS support from GNU C Library. In the first step only the slower syscall is used for TLS access. The uClibc-ng testsuite shows 79 errors, so their is room for bugfixes and improvements.
Diffstat (limited to 'ldso')
-rw-r--r--ldso/ldso/m68k/dl-sysdep.h12
-rw-r--r--ldso/ldso/m68k/elfinterp.c45
-rw-r--r--ldso/ldso/m68k/m68k_read_tp.S48
3 files changed, 90 insertions, 15 deletions
diff --git a/ldso/ldso/m68k/dl-sysdep.h b/ldso/ldso/m68k/dl-sysdep.h
index 8ac892655..21937b259 100644
--- a/ldso/ldso/m68k/dl-sysdep.h
+++ b/ldso/ldso/m68k/dl-sysdep.h
@@ -27,12 +27,16 @@ do { \
struct elf_resolve;
extern unsigned long _dl_linux_resolver (struct elf_resolve *, int);
-/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry, so
- PLT entries should not be allowed to define the value.
- ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one
+/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry or
+ TLS variable, so undefined references should not be allowed to
+ define the value.
+ ELF_RTYPE_CLASS_COPY iff TYPE should not be allowed to resolve to one
of the main executable's symbols, as for a COPY reloc. */
#define elf_machine_type_class(type) \
- ((((type) == R_68K_JMP_SLOT) * ELF_RTYPE_CLASS_PLT) \
+ ((((type) == R_68K_JMP_SLOT \
+ || (type) == R_68K_TLS_DTPMOD32 \
+ || (type) == R_68K_TLS_DTPREL32 \
+ || (type) == R_68K_TLS_TPREL32) * ELF_RTYPE_CLASS_PLT) \
| (((type) == R_68K_COPY) * ELF_RTYPE_CLASS_COPY))
/* Return the link-time address of _DYNAMIC. Conveniently, this is the
diff --git a/ldso/ldso/m68k/elfinterp.c b/ldso/ldso/m68k/elfinterp.c
index 15a2c43b1..25ea23067 100644
--- a/ldso/ldso/m68k/elfinterp.c
+++ b/ldso/ldso/m68k/elfinterp.c
@@ -150,6 +150,9 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct r_scope_elem *scope,
#if defined (__SUPPORT_LD_DEBUG__)
ElfW(Addr) old_val;
#endif
+#if defined USE_TLS && USE_TLS
+ struct elf_resolve *tls_tpnt = NULL;
+#endif
reloc_addr = (ElfW(Addr)*)(tpnt->loadaddr + (unsigned long)rpnt->r_offset);
reloc_type = ELF_R_TYPE(rpnt->r_info);
@@ -167,16 +170,28 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct r_scope_elem *scope,
* might have been intentional. We should not be linking local
* symbols here, so all bases should be covered.
*/
- if (unlikely(!symbol_addr && ELF_ST_BIND(sym_ref.sym->st_info) != STB_WEAK)) {
- _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", _dl_progname, symname);
- _dl_exit(1);
+ if (unlikely (!symbol_addr &&
+ ELF_ST_TYPE (sym_ref.sym->st_info) != STT_TLS &&
+ ELF_ST_BIND (sym_ref.sym->st_info) != STB_WEAK)) {
+ return 1;
}
if (_dl_trace_prelink) {
_dl_debug_lookup (symname, tpnt, &symtab[symtab_index],
&sym_ref, elf_machine_type_class(reloc_type));
}
+#if defined USE_TLS && USE_TLS
+ tls_tpnt = sym_ref.tpnt;
+#endif
}
+#if defined USE_TLS && USE_TLS
+ /* In case of a TLS reloc, tls_tpnt NULL means we have an 'anonymous'
+ symbol. This is the case for a static tls variable, so the lookup
+ module is just that one is referencing the tls variable. */
+ if (!tls_tpnt)
+ tls_tpnt = tpnt;
+#endif
+
#if defined (__SUPPORT_LD_DEBUG__)
old_val = *reloc_addr;
#endif
@@ -209,13 +224,6 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct r_scope_elem *scope,
case R_68K_JMP_SLOT:
*reloc_addr = symbol_addr + rpnt->r_addend;
break;
- /* handled by elf_machine_relative()
- case R_68K_RELATIVE:
- *reloc_addr = ((unsigned int) tpnt->loadaddr
- / * Compatibility kludge. * /
- + (rpnt->r_addend ? : *reloc_addr));
- */
- break;
case R_68K_COPY:
if (symbol_addr) {
#if defined (__SUPPORT_LD_DEBUG__)
@@ -234,7 +242,22 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct r_scope_elem *scope,
_dl_dprintf(_dl_debug_file, "no symbol_addr to copy !?\n");
#endif
break;
-
+#if defined USE_TLS && USE_TLS
+ case R_68K_TLS_DTPMOD32:
+ *reloc_addr = tls_tpnt->l_tls_modid;
+ break;
+ case R_68K_TLS_DTPREL32:
+ if (sym_ref.sym != NULL)
+ *reloc_addr = TLS_DTPREL_VALUE (sym_ref.sym, rpnt);
+ break;
+ case R_68K_TLS_TPREL32:
+ if (sym_ref.sym != NULL)
+ {
+ CHECK_STATIC_TLS ((struct link_map *) tls_tpnt);
+ *reloc_addr = TLS_TPREL_VALUE ((struct link_map *) tls_tpnt, sym_ref.sym, rpnt);
+ }
+ break;
+#endif
default:
return -1; /* Calls _dl_exit(1). */
}
diff --git a/ldso/ldso/m68k/m68k_read_tp.S b/ldso/ldso/m68k/m68k_read_tp.S
new file mode 100644
index 000000000..cb5280e67
--- /dev/null
+++ b/ldso/ldso/m68k/m68k_read_tp.S
@@ -0,0 +1,48 @@
+/* Copyright (C) 2010-2017 Free Software Foundation, Inc.
+ Contributed by Maxim Kuvyrkov <maxim@codesourcery.com>, 2010.
+
+ 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.
+
+ In addition to the permissions in the GNU Lesser General Public
+ License, the Free Software Foundation gives you unlimited
+ permission to link the compiled version of this file with other
+ programs, and to distribute those programs without any restriction
+ coming from the use of this file. (The GNU Lesser General Public
+ License restrictions do apply in other respects; for example, they
+ cover modification of the file, and distribution when not linked
+ into another program.)
+
+ Note that people who make modified versions of this file are not
+ obligated to grant this special exception for their modified
+ versions; it is their choice whether to do so. The GNU Lesser
+ General Public License gives permission to release a modified
+ version without this exception; this exception also makes it
+ possible to release a modified version which carries forward this
+ exception.
+
+ 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+
+ .text
+# ifdef IS_IN_rtld
+/* rtld gets a hidden copy of __m68k_read_tp. */
+ .hidden __m68k_read_tp
+# endif
+
+ENTRY (__m68k_read_tp)
+ move.l #__NR_get_thread_area, %d0
+ trap #0
+ move.l %d0, %a0
+ rts
+END (__m68k_read_tp)