-/* Copyright (C) 1992, 1993, 1995, 1996, 1997, 1998, 1999, 2000, 2002, 2003 Free Software Foundation, Inc.
+/* Copyright (C) 1992-2019 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper, <drepper@gnu.ai.mit.edu>, August 1995.
Changed by Kaz Kojima, <kkojima@rr.iij4u.or.jp>.
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. */
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
#ifndef _LINUX_SH_SYSDEP_H
#define _LINUX_SH_SYSDEP_H 1
/* There is some commonality. */
+#include <sysdeps/unix/sysv/linux/sysdep.h>
#include <sysdeps/unix/sh/sysdep.h>
+#include <tls.h>
/* For Linux we can use the system call table in the header file
/usr/include/asm/unistd.h
# if RTLD_PRIVATE_ERRNO
# define SYSCALL_ERROR_HANDLER \
neg r0,r1; \
+ mov r12,r2; \
+ cfi_register (r12, r2); \
mov.l 0f,r12; \
mova 0f,r0; \
add r0,r12; \
mov.l 1f,r0; \
- mov.l r1,@(r0,r12)
+ mov.l r1,@(r0,r12); \
+ mov r2,r12; \
+ cfi_restore (r12); \
bra .Lpseudo_end; \
mov _IMM1,r0; \
.align 2; \
0: .long _GLOBAL_OFFSET_TABLE_; \
- 1: .long errno@GOTOFF
+ 1: .long rtld_errno@GOTOFF
# elif defined _LIBC_REENTRANT
-# if USE___THREAD
-# ifndef NOT_IN_libc
-# define SYSCALL_ERROR_ERRNO __libc_errno
-# else
-# define SYSCALL_ERROR_ERRNO errno
-# endif
-# define SYSCALL_ERROR_HANDLER \
+# if IS_IN (libc)
+# define SYSCALL_ERROR_ERRNO __libc_errno
+# else
+# define SYSCALL_ERROR_ERRNO errno
+# endif
+# define SYSCALL_ERROR_HANDLER \
neg r0,r1; \
mov r12,r2; \
+ cfi_register (r12, r2); \
mov.l 0f,r12; \
mova 0f,r0; \
add r0,r12; \
stc gbr, r4; \
mov.l @(r0,r12),r0; \
mov r2,r12; \
+ cfi_restore (r12); \
add r4,r0; \
mov.l r1,@r0; \
bra .Lpseudo_end; \
.align 2; \
0: .long _GLOBAL_OFFSET_TABLE_; \
1: .long SYSCALL_ERROR_ERRNO@GOTTPOFF
-# else
-# define SYSCALL_ERROR_HANDLER \
- neg r0,r1; \
- mov.l r14,@-r15; \
- mov.l r12,@-r15; \
- mov.l r1,@-r15; \
- mov.l 0f,r12; \
- mova 0f,r0; \
- add r0,r12; \
- sts.l pr,@-r15; \
- mov r15,r14; \
- mov.l 1f,r1; \
- bsrf r1; \
- nop; \
- 2: mov r14,r15; \
- lds.l @r15+,pr; \
- mov.l @r15+,r1; \
- mov.l r1,@r0; \
- mov.l @r15+,r12; \
- mov.l @r15+,r14; \
- bra .Lpseudo_end; \
- mov _IMM1,r0; \
- .align 2; \
- 0: .long _GLOBAL_OFFSET_TABLE_; \
- 1: .long PLTJMP(C_SYMBOL_NAME(__errno_location))-(2b+2-.)
-/* A quick note: it is assumed that the call to `__errno_location' does
- not modify the stack! */
-# endif
# else
/* Store (-r0) into errno through the GOT. */
# define SYSCALL_ERROR_HANDLER \
neg r0,r1; \
mov r12,r2; \
+ cfi_register (r12, r2); \
mov.l 0f,r12; \
mova 0f,r0; \
add r0,r12; \
mov.l 1f,r0; \
mov.l @(r0,r12),r0; \
mov r2,r12; \
+ cfi_restore (r12); \
mov.l r1,@r0; \
bra .Lpseudo_end; \
mov _IMM1,r0; \
# endif /* _LIBC_REENTRANT */
#endif /* PIC */
+# ifdef NEED_SYSCALL_INST_PAD
+# define SYSCALL_INST_PAD \
+ or r0,r0; or r0,r0; or r0,r0; or r0,r0; or r0,r0
+# else
+# define SYSCALL_INST_PAD
+# endif
+
#define SYSCALL_INST0 trapa #0x10
#define SYSCALL_INST1 trapa #0x11
#define SYSCALL_INST2 trapa #0x12
#define DO_CALL(syscall_name, args) \
mov.l 1f,r3; \
SYSCALL_INST##args; \
+ SYSCALL_INST_PAD; \
bra 2f; \
nop; \
.align 2; \
1: .long SYS_ify (syscall_name); \
2:
-# ifdef NEED_SYSCALL_INST_PAD
-# define SYSCALL_INST_PAD \
- or r0,r0; or r0,r0; or r0,r0; or r0,r0; or r0,r0
-# else
-# define SYSCALL_INST_PAD
-# endif
-
#else /* not __ASSEMBLER__ */
#define SYSCALL_INST_STR0 "trapa #0x10\n\t"
, "r" (r4), "r" (r5), "r" (r6), "r" (r7), "0" (r0), "r" (r1), "r" (r2)
#define SUBSTITUTE_ARGS_0()
-#define SUBSTITUTE_ARGS_1(arg1) \
- register long r4 asm ("%r4") = (long)(arg1)
-#define SUBSTITUTE_ARGS_2(arg1, arg2) \
- register long r4 asm ("%r4") = (long)(arg1); \
- register long r5 asm ("%r5") = (long)(arg2)
-#define SUBSTITUTE_ARGS_3(arg1, arg2, arg3) \
- register long r4 asm ("%r4") = (long)(arg1); \
- register long r5 asm ("%r5") = (long)(arg2); \
- register long r6 asm ("%r6") = (long)(arg3)
-#define SUBSTITUTE_ARGS_4(arg1, arg2, arg3, arg4) \
- register long r4 asm ("%r4") = (long)(arg1); \
- register long r5 asm ("%r5") = (long)(arg2); \
- register long r6 asm ("%r6") = (long)(arg3); \
- register long r7 asm ("%r7") = (long)(arg4)
-#define SUBSTITUTE_ARGS_5(arg1, arg2, arg3, arg4, arg5) \
- register long r4 asm ("%r4") = (long)(arg1); \
- register long r5 asm ("%r5") = (long)(arg2); \
- register long r6 asm ("%r6") = (long)(arg3); \
- register long r7 asm ("%r7") = (long)(arg4); \
- register long r0 asm ("%r0") = (long)(arg5)
-#define SUBSTITUTE_ARGS_6(arg1, arg2, arg3, arg4, arg5, arg6) \
- register long r4 asm ("%r4") = (long)(arg1); \
- register long r5 asm ("%r5") = (long)(arg2); \
- register long r6 asm ("%r6") = (long)(arg3); \
- register long r7 asm ("%r7") = (long)(arg4); \
- register long r0 asm ("%r0") = (long)(arg5); \
- register long r1 asm ("%r1") = (long)(arg6)
-#define SUBSTITUTE_ARGS_7(arg1, arg2, arg3, arg4, arg5, arg6, arg7) \
- register long r4 asm ("%r4") = (long)(arg1); \
- register long r5 asm ("%r5") = (long)(arg2); \
- register long r6 asm ("%r6") = (long)(arg3); \
- register long r7 asm ("%r7") = (long)(arg4); \
- register long r0 asm ("%r0") = (long)(arg5) \
- register long r1 asm ("%r1") = (long)(arg6); \
- register long r2 asm ("%r2") = (long)(arg7)
+#define SUBSTITUTE_ARGS_1(arg1) \
+ long int _arg1 = (long int) (arg1); \
+ register long int r4 asm ("%r4") = (long int) (_arg1)
+#define SUBSTITUTE_ARGS_2(arg1, arg2) \
+ long int _arg1 = (long int) (arg1); \
+ long int _arg2 = (long int) (arg2); \
+ register long int r4 asm ("%r4") = (long int) (_arg1); \
+ register long int r5 asm ("%r5") = (long int) (_arg2)
+#define SUBSTITUTE_ARGS_3(arg1, arg2, arg3) \
+ long int _arg1 = (long int) (arg1); \
+ long int _arg2 = (long int) (arg2); \
+ long int _arg3 = (long int) (arg3); \
+ register long int r4 asm ("%r4") = (long int) (_arg1); \
+ register long int r5 asm ("%r5") = (long int) (_arg2); \
+ register long int r6 asm ("%r6") = (long int) (_arg3)
+#define SUBSTITUTE_ARGS_4(arg1, arg2, arg3, arg4) \
+ long int _arg1 = (long int) (arg1); \
+ long int _arg2 = (long int) (arg2); \
+ long int _arg3 = (long int) (arg3); \
+ long int _arg4 = (long int) (arg4); \
+ register long int r4 asm ("%r4") = (long int) (_arg1); \
+ register long int r5 asm ("%r5") = (long int) (_arg2); \
+ register long int r6 asm ("%r6") = (long int) (_arg3); \
+ register long int r7 asm ("%r7") = (long int) (_arg4)
+#define SUBSTITUTE_ARGS_5(arg1, arg2, arg3, arg4, arg5) \
+ long int _arg1 = (long int) (arg1); \
+ long int _arg2 = (long int) (arg2); \
+ long int _arg3 = (long int) (arg3); \
+ long int _arg4 = (long int) (arg4); \
+ long int _arg5 = (long int) (arg5); \
+ register long int r4 asm ("%r4") = (long int) (_arg1); \
+ register long int r5 asm ("%r5") = (long int) (_arg2); \
+ register long int r6 asm ("%r6") = (long int) (_arg3); \
+ register long int r7 asm ("%r7") = (long int) (_arg4); \
+ register long int r0 asm ("%r0") = (long int) (_arg5)
+#define SUBSTITUTE_ARGS_6(arg1, arg2, arg3, arg4, arg5, arg6) \
+ long int _arg1 = (long int) (arg1); \
+ long int _arg2 = (long int) (arg2); \
+ long int _arg3 = (long int) (arg3); \
+ long int _arg4 = (long int) (arg4); \
+ long int _arg5 = (long int) (arg5); \
+ long int _arg6 = (long int) (arg6); \
+ register long int r4 asm ("%r4") = (long int)(_arg1); \
+ register long int r5 asm ("%r5") = (long int) (_arg2); \
+ register long int r6 asm ("%r6") = (long int) (_arg3); \
+ register long int r7 asm ("%r7") = (long int) (_arg4); \
+ register long int r0 asm ("%r0") = (long int) (_arg5); \
+ register long int r1 asm ("%r1") = (long int) (_arg6)
+#define SUBSTITUTE_ARGS_7(arg1, arg2, arg3, arg4, arg5, arg6, arg7) \
+ long int _arg1 = (long int) (arg1); \
+ long int _arg2 = (long int) (arg2); \
+ long int _arg3 = (long int) (arg3); \
+ long int _arg4 = (long int) (arg4); \
+ long int _arg5 = (long int) (arg5); \
+ long int _arg6 = (long int) (arg6); \
+ long int _arg7 = (long int) (arg7); \
+ register long int r4 asm ("%r4") = (long int) (_arg1); \
+ register long int r5 asm ("%r5") = (long int) (_arg2); \
+ register long int r6 asm ("%r6") = (long int) (_arg3); \
+ register long int r7 asm ("%r7") = (long int) (_arg4); \
+ register long int r0 asm ("%r0") = (long int) (_arg5); \
+ register long int r1 asm ("%r1") = (long int) (_arg6); \
+ register long int r2 asm ("%r2") = (long int) (_arg7)
#undef INLINE_SYSCALL
#define INLINE_SYSCALL(name, nr, args...) \
unsigned int resultvar = INTERNAL_SYSCALL (name, , nr, args); \
if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (resultvar, ), 0)) \
{ \
- __set_errno (INTERNAL_SYSCALL_ERRNO (resultvar, )); \
- resultvar = 0xffffffff; \
+ __set_errno (INTERNAL_SYSCALL_ERRNO (resultvar, )); \
+ resultvar = 0xffffffff; \
} \
(int) resultvar; })
#undef INTERNAL_SYSCALL
#define INTERNAL_SYSCALL(name, err, nr, args...) \
- ({ \
- unsigned long resultvar; \
- register long r3 asm ("%r3") = SYS_ify (name); \
- SUBSTITUTE_ARGS_##nr(args); \
- \
- asm volatile (SYSCALL_INST_STR##nr SYSCALL_INST_PAD \
- : "=z" (resultvar) \
- : "r" (r3) ASMFMT_##nr \
- : "memory"); \
- \
+ ({ \
+ unsigned long int resultvar; \
+ register long int r3 asm ("%r3") = SYS_ify (name); \
+ SUBSTITUTE_ARGS_##nr(args); \
+ \
+ asm volatile (SYSCALL_INST_STR##nr SYSCALL_INST_PAD \
+ : "=z" (resultvar) \
+ : "r" (r3) ASMFMT_##nr \
+ : "memory", "t"); \
+ \
+ (int) resultvar; })
+
+/* The _NCS variant allows non-constant syscall numbers. */
+#define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \
+ ({ \
+ unsigned long int resultvar; \
+ register long int r3 asm ("%r3") = (name); \
+ SUBSTITUTE_ARGS_##nr(args); \
+ \
+ asm volatile (SYSCALL_INST_STR##nr SYSCALL_INST_PAD \
+ : "=z" (resultvar) \
+ : "r" (r3) ASMFMT_##nr \
+ : "memory", "t"); \
+ \
(int) resultvar; })
#undef INTERNAL_SYSCALL_DECL
#endif /* __ASSEMBLER__ */
+/* Pointer mangling support. */
+#if IS_IN (rtld)
+/* We cannot use the thread descriptor because in ld.so we use setjmp
+ earlier than the descriptor is initialized. Using a global variable
+ is too complicated here since we have no PC-relative addressing mode. */
+#else
+# ifdef __ASSEMBLER__
+# define PTR_MANGLE(reg, tmp) \
+ stc gbr,tmp; mov.l @(POINTER_GUARD,tmp),tmp; xor tmp,reg
+# define PTR_MANGLE2(reg, tmp) xor tmp,reg
+# define PTR_DEMANGLE(reg, tmp) PTR_MANGLE (reg, tmp)
+# define PTR_DEMANGLE2(reg, tmp) PTR_MANGLE2 (reg, tmp)
+# else
+# define PTR_MANGLE(var) \
+ (var) = (void *) ((uintptr_t) (var) ^ THREAD_GET_POINTER_GUARD ())
+# define PTR_DEMANGLE(var) PTR_MANGLE (var)
+# endif
+#endif
+
#endif /* linux/sh/sysdep.h */