diff options
author | Waldemar Brodkorb <wbx@uclibc-ng.org> | 2017-12-16 21:01:39 +0100 |
---|---|---|
committer | Waldemar Brodkorb <wbx@uclibc-ng.org> | 2017-12-31 11:12:07 +0100 |
commit | 23bb649090ff588e8642f0c581cfe7ce2d29c757 (patch) | |
tree | 4a68d696415fce9f2dd50edf27a79bacbde3fc50 | |
parent | 604781391549faafc59516700d9439ab1a7ec19b (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.
31 files changed, 1442 insertions, 71 deletions
diff --git a/extra/Configs/Config.in b/extra/Configs/Config.in index b5ee294db..181d459fb 100644 --- a/extra/Configs/Config.in +++ b/extra/Configs/Config.in @@ -544,7 +544,6 @@ config UCLIBC_HAS_THREADS_NATIVE !TARGET_h8300 && \ !TARGET_hppa && \ !TARGET_ia64 && \ - !TARGET_m68k && \ ARCH_USE_MMU help If you want to compile uClibc with NPTL support, then answer Y. diff --git a/include/elf.h b/include/elf.h index fcb546a0f..6b0a8757e 100644 --- a/include/elf.h +++ b/include/elf.h @@ -1292,8 +1292,29 @@ typedef struct #define R_68K_GLOB_DAT 20 /* Create GOT entry */ #define R_68K_JMP_SLOT 21 /* Create PLT entry */ #define R_68K_RELATIVE 22 /* Adjust by program base */ +#define R_68K_TLS_GD32 25 /* 32 bit GOT offset for GD */ +#define R_68K_TLS_GD16 26 /* 16 bit GOT offset for GD */ +#define R_68K_TLS_GD8 27 /* 8 bit GOT offset for GD */ +#define R_68K_TLS_LDM32 28 /* 32 bit GOT offset for LDM */ +#define R_68K_TLS_LDM16 29 /* 16 bit GOT offset for LDM */ +#define R_68K_TLS_LDM8 30 /* 8 bit GOT offset for LDM */ +#define R_68K_TLS_LDO32 31 /* 32 bit module-relative offset */ +#define R_68K_TLS_LDO16 32 /* 16 bit module-relative offset */ +#define R_68K_TLS_LDO8 33 /* 8 bit module-relative offset */ +#define R_68K_TLS_IE32 34 /* 32 bit GOT offset for IE */ +#define R_68K_TLS_IE16 35 /* 16 bit GOT offset for IE */ +#define R_68K_TLS_IE8 36 /* 8 bit GOT offset for IE */ +#define R_68K_TLS_LE32 37 /* 32 bit offset relative to + static TLS block */ +#define R_68K_TLS_LE16 38 /* 16 bit offset relative to + static TLS block */ +#define R_68K_TLS_LE8 39 /* 8 bit offset relative to + static TLS block */ +#define R_68K_TLS_DTPMOD32 40 /* 32 bit module number */ +#define R_68K_TLS_DTPREL32 41 /* 32 bit module-relative offset */ +#define R_68K_TLS_TPREL32 42 /* 32 bit TP-relative offset */ /* Keep this the last entry. */ -#define R_68K_NUM 23 +#define R_68K_NUM 43 /* Intel 80386 specific definitions. */ 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) diff --git a/libc/sysdeps/linux/common/libgcc_s.h b/libc/sysdeps/linux/common/libgcc_s.h index e74a1034c..bf43d78a7 100644 --- a/libc/sysdeps/linux/common/libgcc_s.h +++ b/libc/sysdeps/linux/common/libgcc_s.h @@ -1,2 +1,6 @@ /* Name of libgcc_s library provided by gcc. */ +#if defined(__m68k__) +#define LIBGCC_S_SO "libgcc_s.so.2" +#else #define LIBGCC_S_SO "libgcc_s.so.1" +#endif diff --git a/libc/sysdeps/linux/m68k/Makefile.arch b/libc/sysdeps/linux/m68k/Makefile.arch index 88caa116f..191791aef 100644 --- a/libc/sysdeps/linux/m68k/Makefile.arch +++ b/libc/sysdeps/linux/m68k/Makefile.arch @@ -7,4 +7,5 @@ CSRC-y := brk.c __syscall_error.c -SSRC-y := __longjmp.S bsd-_setjmp.S bsd-setjmp.S clone.S setjmp.S vfork.S +SSRC-y := __longjmp.S bsd-_setjmp.S bsd-setjmp.S clone.S setjmp.S vfork.S \ + m68k_read_tp.S diff --git a/libc/sysdeps/linux/m68k/clone.S b/libc/sysdeps/linux/m68k/clone.S index 7eddff10c..24071235b 100644 --- a/libc/sysdeps/linux/m68k/clone.S +++ b/libc/sysdeps/linux/m68k/clone.S @@ -1,54 +1,94 @@ -/* Adapted from glibc */ -/* Copyright (C) 1996, 1997 Free Software Foundation, Inc. */ +/* Copyright (C) 1996-2017 Free Software Foundation, Inc. + Contributed by Andreas Schwab (schwab@issan.informatik.uni-dortmund.de) + + 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, see + <http://www.gnu.org/licenses/>. */ /* clone is even more special than fork as it mucks with stacks and invokes a function in the right context after its all over. */ #define _ERRNO_H +#include <sysdep.h> #include <features.h> #include <bits/errno.h> #include <sys/syscall.h> #include "m68k_pic.S" -/* int _clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg); */ +/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg, + void *parent_tidptr, void *tls, void *child_tidptr) */ -.text -.align 4 -.type clone,@function -.globl clone; -clone: + .text + .align 4 + .globl __clone + .type __clone,@function + +__clone: /* Sanity check arguments. */ - movel #-EINVAL, %d0 - movel 4(%sp), %d1 /* no NULL function pointers */ - movel %d1, %a0 - tstl %d1 + movel #-EINVAL, %d0 + movel 4(%sp), %a0 /* no NULL function pointers */ + tstl %a0 beq.w __syscall_error_trampoline - movel 8(%sp), %d1 /* no NULL stack pointers */ - movel %d1, %a1 - tstl %d1 + movel 8(%sp), %a1 /* no NULL stack pointers */ + tstl %a1 beq.w __syscall_error_trampoline /* Allocate space and copy the argument onto the new stack. */ movel 16(%sp), -(%a1) /* Do the system call */ -#if 1 /* defined (CONFIG_COLDFIRE) */ - movel %d2, %d1 /* save %d2 and get stack pointer */ - movel %a1, %d2 - movel %d1, %a1 + movel 12(%sp), %d1 /* get flags */ + movel %d3, -(%a1) /* save %d3 and get parent_tidptr */ + movel %d3, -(%sp) + cfi_adjust_cfa_offset (4) + cfi_rel_offset (%d3, 0) + movel 20+4(%sp), %d3 + movel %d4, -(%a1) /* save %d4 and get child_tidptr */ + movel %d4, -(%sp) + cfi_adjust_cfa_offset (4) + cfi_rel_offset (%d4, 0) + movel 28+8(%sp), %d4 + movel %d5, -(%a1) /* save %d5 and get tls */ + movel %d5, -(%sp) + cfi_adjust_cfa_offset (4) + cfi_rel_offset (%d5, 0) + movel 24+12(%sp), %d5 + /* save %d2 and get stack pointer */ +#ifdef __mcoldfire__ + movel %d2, -(%a1) + movel %d2, -(%sp) + cfi_adjust_cfa_offset (4) + cfi_rel_offset (%d2, 0) + movel %a1, %d2 #else - exg %d2, %a1 /* save %d2 and get stack pointer */ + exg %d2, %a1 /* save %d2 and get stack pointer */ + cfi_register (%d2, %a1) #endif - movel 12(%sp), %d1 /* get flags */ movel #__NR_clone, %d0 + + /* End FDE now, because in the child the unwind info will be + wrong. */ + cfi_endproc + trap #0 -#if 1 /* defined (CONFIG_COLDFIRE) */ - movel %d2, %d1 /* restore %d2 */ - movel %a1, %d2 - movel %d1, %a1 +#ifdef __mcoldfire__ + movel (%sp)+, %d2 #else - exg %d2, %a1 /* restore %d2 */ + exg %d2, %a1 /* restore %d2 */ #endif + movel (%sp)+, %d5 /* restore %d5, %d4 and %d3 */ + movel (%sp)+, %d4 + movel (%sp)+, %d3 tstl %d0 bmi.w __syscall_error_trampoline @@ -57,13 +97,21 @@ clone: rts thread_start: - /*subl %fp, %fp*/ /* terminate the stack frame */ - jsr (%a0) - movel %d0, -(%sp) + cfi_startproc + cfi_undefined (pc) /* Mark end of stack */ + subl %fp, %fp /* terminate the stack frame */ + jsr (%a0) + movel %d0, %d1 movel #__NR_exit, %d0 trap #0 - /*jsr exit*/ + cfi_endproc + + cfi_startproc __syscall_error_trampoline: JUMP __syscall_error,%a0 +.size __clone,.-__clone + +weak_alias(__clone,clone) +libc_hidden_def(clone) diff --git a/libc/sysdeps/linux/m68k/jmpbuf-unwind.h b/libc/sysdeps/linux/m68k/jmpbuf-unwind.h index c5a8886e2..8744ec7e8 100644 --- a/libc/sysdeps/linux/m68k/jmpbuf-unwind.h +++ b/libc/sysdeps/linux/m68k/jmpbuf-unwind.h @@ -1,8 +1,19 @@ -/* - * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org> - * - * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. - */ +/* Examine __jmp_buf for unwinding frames. m68k version. + Copyright (C) 2006-2017 Free Software Foundation, Inc. + + 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, see + <http://www.gnu.org/licenses/>. */ #include <setjmp.h> @@ -10,3 +21,21 @@ containing a local variable at ADDRESS. */ #define _JMPBUF_UNWINDS(jmpbuf, address) \ ((void *) (address) < (void *) (jmpbuf)->__aregs[5]) + +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ +#include <stdint.h> +#include <unwind.h> + +#define _JMPBUF_CFA_UNWINDS_ADJ(_jmpbuf, _context, _adj) \ + _JMPBUF_UNWINDS_ADJ (_jmpbuf, (void *) _Unwind_GetCFA (_context), _adj) + +static inline uintptr_t __attribute__ ((unused)) +_jmpbuf_sp (__jmp_buf regs) +{ + uintptr_t sp = (uintptr_t) regs[0].__sp; + return sp; +} + +#define _JMPBUF_UNWINDS_ADJ(_jmpbuf, _address, _adj) \ + ((uintptr_t) (_address) - (_adj) < _jmpbuf_sp (_jmpbuf) - (_adj)) +#endif diff --git a/libc/sysdeps/linux/m68k/m68k_read_tp.S b/libc/sysdeps/linux/m68k/m68k_read_tp.S new file mode 100644 index 000000000..523e1b38a --- /dev/null +++ b/libc/sysdeps/linux/m68k/m68k_read_tp.S @@ -0,0 +1 @@ +#include <ldso/ldso/m68k/m68k_read_tp.S> diff --git a/libc/sysdeps/linux/m68k/sys/reg.h b/libc/sysdeps/linux/m68k/sys/reg.h new file mode 100644 index 000000000..133c862b4 --- /dev/null +++ b/libc/sysdeps/linux/m68k/sys/reg.h @@ -0,0 +1,101 @@ +/* Copyright (C) 1998-2017 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, see + <http://www.gnu.org/licenses/>. */ + +#ifndef _SYS_REG_H +#define _SYS_REG_H 1 + +/* Index into an array of 4 byte integers returned from ptrace for + location of the users' stored general purpose registers. */ + +enum +{ + PT_D1 = 0, +#define PT_D1 PT_D1 + PT_D2 = 1, +#define PT_D2 PT_D2 + PT_D3 = 2, +#define PT_D3 PT_D3 + PT_D4 = 3, +#define PT_D4 PT_D4 + PT_D5 = 4, +#define PT_D5 PT_D5 + PT_D6 = 5, +#define PT_D6 PT_D6 + PT_D7 = 6, +#define PT_D7 PT_D7 + PT_A0 = 7, +#define PT_A0 PT_A0 + PT_A1 = 8, +#define PT_A1 PT_A1 + PT_A2 = 9, +#define PT_A2 PT_A2 + PT_A3 = 10, +#define PT_A3 PT_A3 + PT_A4 = 11, +#define PT_A4 PT_A4 + PT_A5 = 12, +#define PT_A5 PT_A5 + PT_A6 = 13, +#define PT_A6 PT_A6 + PT_D0 = 14, +#define PT_D0 PT_D0 + PT_USP = 15, +#define PT_USP PT_USP + PT_ORIG_D0 = 16, +#define PT_ORIG_D0 PT_ORIG_D0 + PT_SR = 17, +#define PT_SR PT_SR + PT_PC = 18, +#define PT_PC PT_PC + +#ifdef __mcoldfire__ + PT_FP0 = 21, + PT_FP1 = 23, + PT_FP2 = 25, + PT_FP3 = 27, + PT_FP4 = 29, + PT_FP5 = 31, + PT_FP6 = 33, + PT_FP7 = 35, +#else + PT_FP0 = 21, + PT_FP1 = 24, + PT_FP2 = 27, + PT_FP3 = 30, + PT_FP4 = 33, + PT_FP5 = 36, + PT_FP6 = 39, + PT_FP7 = 42, +#endif +#define PT_FP0 PT_FP0 +#define PT_FP1 PT_FP1 +#define PT_FP2 PT_FP2 +#define PT_FP3 PT_FP3 +#define PT_FP4 PT_FP4 +#define PT_FP5 PT_FP5 +#define PT_FP6 PT_FP6 +#define PT_FP7 PT_FP7 + + PT_FPCR = 45, +#define PT_FPCR PT_FPCR + PT_FPSR = 46, +#define PT_FPSR PT_FPSR + PT_FPIAR = 47 +#define PT_FPIAR PT_FPIAR +}; + +#endif /* _SYS_REG_H */ diff --git a/libc/sysdeps/linux/m68k/sysdep.h b/libc/sysdeps/linux/m68k/sysdep.h new file mode 100644 index 000000000..9c18aae97 --- /dev/null +++ b/libc/sysdeps/linux/m68k/sysdep.h @@ -0,0 +1,26 @@ +#include <common/sysdep.h> + +#ifdef __ASSEMBLER__ + +/* Define an entry point visible from C. + + There is currently a bug in gdb which prevents us from specifying + incomplete stabs information. Fake some entries here which specify + the current source file. */ +# define ENTRY(name) \ + .globl C_SYMBOL_NAME(name); \ + .type C_SYMBOL_NAME(name),@function; \ + .p2align 2; \ + C_LABEL(name) \ + cfi_startproc; \ + +# undef END +# define END(name) \ + cfi_endproc; \ + .size name,.-name + +/* Load the address of the GOT into register R. */ +# define LOAD_GOT(R) \ + lea _GLOBAL_OFFSET_TABLE_@GOTPC (%pc), R + +#endif diff --git a/libc/sysdeps/linux/m68k/vfork.S b/libc/sysdeps/linux/m68k/vfork.S index bde9d5a3a..eb1639e37 100644 --- a/libc/sysdeps/linux/m68k/vfork.S +++ b/libc/sysdeps/linux/m68k/vfork.S @@ -10,8 +10,6 @@ #define __NR_vfork __NR_fork /* uClinux-2.0 only has fork which is vfork */ #endif -#define IMM # - .text .align 2 .globl __vfork @@ -19,26 +17,22 @@ .type __vfork,@function __vfork: - movl %sp@+, %a1 /* save the return address for later */ - movl IMM __NR_vfork,%d0 + /* Pop the return PC value into A0. */ + movel %sp@+, %a0 + + /* Stuff the syscall number in D0 and trap into the kernel. */ + movel #SYS_ify (vfork), %d0 trap #0 - movl %a1, -(%sp) - cmpil #-4096,%d0 - blss 1f + tstl %d0 + jmi .Lerror /* Branch forward if it failed. */ - neg.l %d0 -#ifndef __PIC__ /* needs handling as the other archs */ - movl errno, %a0 -#else - movl errno@GOT(%a5), %a0 -#endif - movl %d0, %a0@ - move.l #-1, %d0 + /* Jump to the return PC. */ + jmp %a0@ -1: - move.l %d0, %a0 - rts +.Lerror: + /* Push back the return PC. */ + movel %a0,%sp@- .size __vfork,.-__vfork weak_alias(__vfork,vfork) diff --git a/libpthread/nptl/sysdeps/m68k/Makefile b/libpthread/nptl/sysdeps/m68k/Makefile new file mode 100644 index 000000000..43dc60a42 --- /dev/null +++ b/libpthread/nptl/sysdeps/m68k/Makefile @@ -0,0 +1,6 @@ +top_srcdir=../../../../ +top_builddir=../../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.arch +include $(top_srcdir)Makerules diff --git a/libpthread/nptl/sysdeps/m68k/Makefile.arch b/libpthread/nptl/sysdeps/m68k/Makefile.arch new file mode 100644 index 000000000..7f6e1cd5b --- /dev/null +++ b/libpthread/nptl/sysdeps/m68k/Makefile.arch @@ -0,0 +1 @@ +libc_arch_a_CSRC = libc-tls.c diff --git a/libpthread/nptl/sysdeps/m68k/dl-tls.h b/libpthread/nptl/sysdeps/m68k/dl-tls.h new file mode 100644 index 000000000..c0af06e1e --- /dev/null +++ b/libpthread/nptl/sysdeps/m68k/dl-tls.h @@ -0,0 +1,46 @@ +/* Thread-local storage handling in the ELF dynamic linker. M68K version. + 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. + + 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/>. */ + + +/* Type used for the representation of TLS information in the GOT. */ +typedef struct +{ + unsigned long int ti_module; + unsigned long int ti_offset; +} tls_index; + +/* The thread pointer points 0x7000 past the first static TLS block. */ +#define TLS_TP_OFFSET 0x7000 + +/* Dynamic thread vector pointers point 0x8000 past the start of each + TLS block. */ +#define TLS_DTV_OFFSET 0x8000 + +/* Compute the value for a TPREL reloc. */ +#define TLS_TPREL_VALUE(sym_map, sym, reloc) \ + ((sym_map)->l_tls_offset + (sym)->st_value + (reloc)->r_addend \ + - TLS_TP_OFFSET) + +/* Compute the value for a DTPREL reloc. */ +#define TLS_DTPREL_VALUE(sym, reloc) \ + ((sym)->st_value + (reloc)->r_addend - TLS_DTV_OFFSET) + +extern void *__tls_get_addr (tls_index *ti); + +#define GET_ADDR_OFFSET (ti->ti_offset + TLS_DTV_OFFSET) +#define __TLS_GET_ADDR(__ti) (__tls_get_addr (__ti) - TLS_DTV_OFFSET) diff --git a/libpthread/nptl/sysdeps/m68k/libc-tls.c b/libpthread/nptl/sysdeps/m68k/libc-tls.c new file mode 100644 index 000000000..50fc030af --- /dev/null +++ b/libpthread/nptl/sysdeps/m68k/libc-tls.c @@ -0,0 +1,32 @@ +/* Thread-local storage handling in the ELF dynamic linker. m68k version. + 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. + + 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 <sysdeps/generic/libc-tls.c> +#include <dl-tls.h> + +/* On M68K, linker optimizations are not required, so __tls_get_addr + can be called even in statically linked binaries. In this case module + must be always 1 and PT_TLS segment exist in the binary, otherwise it + would not link. */ + +void * +__tls_get_addr (tls_index *ti) +{ + dtv_t *dtv = THREAD_DTV (); + return (char *) dtv[1].pointer.val + GET_ADDR_OFFSET; +} diff --git a/libpthread/nptl/sysdeps/m68k/pthread_spin_lock.c b/libpthread/nptl/sysdeps/m68k/pthread_spin_lock.c new file mode 100644 index 000000000..cec3acbc6 --- /dev/null +++ b/libpthread/nptl/sysdeps/m68k/pthread_spin_lock.c @@ -0,0 +1,65 @@ +/* pthread_spin_lock -- lock a spin lock. Generic version. + Copyright (C) 2012-2016 Free Software Foundation, Inc. + + 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 |