summaryrefslogtreecommitdiff
path: root/libc
diff options
context:
space:
mode:
Diffstat (limited to 'libc')
-rw-r--r--libc/misc/internals/reloc_static_pie.c2
-rw-r--r--libc/stdlib/malloc/memalign.c6
-rw-r--r--libc/sysdeps/linux/aarch64/sys/ucontext.h4
-rw-r--r--libc/sysdeps/linux/common-generic/bits/kernel_stat.h2
-rw-r--r--libc/sysdeps/linux/common/futimesat.c1
-rw-r--r--libc/sysdeps/linux/common/not-cancel.h2
-rw-r--r--libc/sysdeps/linux/common/sys/epoll.h14
-rw-r--r--libc/sysdeps/linux/common/utime.c4
-rw-r--r--libc/sysdeps/linux/common/utimensat.c3
-rw-r--r--libc/sysdeps/linux/csky/bits/uClibc_arch_features.h3
-rw-r--r--libc/sysdeps/linux/nds32/Makefile.arch2
-rw-r--r--libc/sysdeps/linux/nds32/bits/kernel_types.h22
-rw-r--r--libc/sysdeps/linux/nds32/bits/syscalls.h3
-rw-r--r--libc/sysdeps/linux/nds32/jmpbuf-unwind.h2
-rw-r--r--libc/sysdeps/linux/nds32/sys/ucontext.h6
-rw-r--r--libc/sysdeps/linux/nds32/vfork.S129
-rw-r--r--libc/sysdeps/linux/riscv32/sys/ucontext.h4
-rw-r--r--libc/sysdeps/linux/riscv64/sys/ucontext.h4
-rw-r--r--libc/sysdeps/linux/sparc64/Makefile.arch2
-rw-r--r--libc/sysdeps/linux/sparc64/sigaction.c10
-rw-r--r--libc/sysdeps/linux/sparc64/sigreturn_stub.S10
-rw-r--r--libc/sysdeps/linux/sparc64/sysdep.h9
-rw-r--r--libc/sysdeps/linux/tile/sys/ucontext.h4
-rw-r--r--libc/sysdeps/linux/xtensa/__start_context.S6
-rw-r--r--libc/sysdeps/linux/xtensa/bits/elf-fdpic.h117
-rw-r--r--libc/sysdeps/linux/xtensa/bits/xtensa-config.h20
-rw-r--r--libc/sysdeps/linux/xtensa/clone.S6
-rw-r--r--libc/sysdeps/linux/xtensa/crt1.S81
-rw-r--r--libc/sysdeps/linux/xtensa/crti.S10
-rw-r--r--libc/sysdeps/linux/xtensa/crtn.S6
-rw-r--r--libc/sysdeps/linux/xtensa/crtreloc.c105
-rw-r--r--libc/sysdeps/linux/xtensa/getcontext.S1
-rw-r--r--libc/sysdeps/linux/xtensa/makecontext.c5
-rw-r--r--libc/sysdeps/linux/xtensa/setcontext.S1
-rw-r--r--libc/sysdeps/linux/xtensa/setjmp.S3
-rw-r--r--libc/sysdeps/linux/xtensa/swapcontext.S1
-rw-r--r--libc/sysdeps/linux/xtensa/sysdep.h48
37 files changed, 614 insertions, 44 deletions
diff --git a/libc/misc/internals/reloc_static_pie.c b/libc/misc/internals/reloc_static_pie.c
index 81af7d666..cb2c4df87 100644
--- a/libc/misc/internals/reloc_static_pie.c
+++ b/libc/misc/internals/reloc_static_pie.c
@@ -21,7 +21,7 @@
#include <dl-elf.h>
#include <ldso.h>
-#if defined(__mips__) || defined(__xtensa__)
+#if defined(__m68k__) || defined(__mips__) || defined(__xtensa__)
#include <dl-startup.h>
#endif
diff --git a/libc/stdlib/malloc/memalign.c b/libc/stdlib/malloc/memalign.c
index 665f20cfb..54f6dbc6c 100644
--- a/libc/stdlib/malloc/memalign.c
+++ b/libc/stdlib/malloc/memalign.c
@@ -11,6 +11,7 @@
* Written by Miles Bader <miles@gnu.org>
*/
+#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>
@@ -38,6 +39,11 @@ memalign (size_t alignment, size_t size)
unsigned long tot_addr, tot_end_addr, addr, end_addr;
struct heap_free_area **heap = &__malloc_heap;
+ if (unlikely(size > PTRDIFF_MAX)) {
+ __set_errno(ENOMEM);
+ return NULL;
+ }
+
/* Make SIZE something we like. */
size = HEAP_ADJUST_SIZE (size);
diff --git a/libc/sysdeps/linux/aarch64/sys/ucontext.h b/libc/sysdeps/linux/aarch64/sys/ucontext.h
index 5f75cbbf3..1a27f918b 100644
--- a/libc/sysdeps/linux/aarch64/sys/ucontext.h
+++ b/libc/sysdeps/linux/aarch64/sys/ucontext.h
@@ -45,10 +45,10 @@ typedef elf_fpregset_t fpregset_t;
typedef struct sigcontext mcontext_t;
/* Userlevel context. */
-typedef struct ucontext_t
+typedef struct ucontext
{
unsigned long uc_flags;
- struct ucontext_t *uc_link;
+ struct ucontext *uc_link;
stack_t uc_stack;
__sigset_t uc_sigmask;
unsigned char __reserved[128];
diff --git a/libc/sysdeps/linux/common-generic/bits/kernel_stat.h b/libc/sysdeps/linux/common-generic/bits/kernel_stat.h
index 7a97bb4d7..e874a4a9f 100644
--- a/libc/sysdeps/linux/common-generic/bits/kernel_stat.h
+++ b/libc/sysdeps/linux/common-generic/bits/kernel_stat.h
@@ -18,7 +18,7 @@
* However that requires more #ifndef in relevant wrappers,
* further uglifying them
*/
-#define kernel_stat64 stat
+#define kernel_stat64 stat64
#endif /* _BITS_STAT_STRUCT_H */
diff --git a/libc/sysdeps/linux/common/futimesat.c b/libc/sysdeps/linux/common/futimesat.c
index fd19fea7c..bf36550dd 100644
--- a/libc/sysdeps/linux/common/futimesat.c
+++ b/libc/sysdeps/linux/common/futimesat.c
@@ -7,6 +7,7 @@
*/
#include <sys/syscall.h>
+#include <sys/stat.h>
#include <sys/time.h>
#ifdef __NR_futimesat
diff --git a/libc/sysdeps/linux/common/not-cancel.h b/libc/sysdeps/linux/common/not-cancel.h
index e4fb1d7fe..426edcc46 100644
--- a/libc/sysdeps/linux/common/not-cancel.h
+++ b/libc/sysdeps/linux/common/not-cancel.h
@@ -19,6 +19,7 @@
#include <sys/types.h>
#include <sysdep.h>
+#include <time.h>
#ifdef NOT_IN_libc
@@ -114,6 +115,7 @@ extern __typeof(pause) __pause_nocancel;
# define nanosleep_not_cancel(requested_time, remaining) \
INLINE_SYSCALL (nanosleep, 2, requested_time, remaining)
#else
+extern int __nanosleep_nocancel (const struct timespec *requested_time, struct timespec *remaining);
# define nanosleep_not_cancel(requested_time, remaining) \
__nanosleep_nocancel (requested_time, remaining)
#endif
diff --git a/libc/sysdeps/linux/common/sys/epoll.h b/libc/sysdeps/linux/common/sys/epoll.h
index 5551bed0d..5138d77a9 100644
--- a/libc/sysdeps/linux/common/sys/epoll.h
+++ b/libc/sysdeps/linux/common/sys/epoll.h
@@ -19,6 +19,7 @@
#define _SYS_EPOLL_H 1
#include <stdint.h>
+#include <sys/ioctl.h>
#include <sys/types.h>
/* Get __sigset_t. */
@@ -87,6 +88,19 @@ struct epoll_event
epoll_data_t data; /* User data variable */
} __EPOLL_PACKED;
+struct epoll_params
+{
+ uint32_t busy_poll_usecs;
+ uint16_t busy_poll_budget;
+ uint8_t prefer_busy_poll;
+
+ /* pad the struct to a multiple of 64bits */
+ uint8_t __pad;
+};
+
+#define EPOLL_IOC_TYPE 0x8A
+#define EPIOCSPARAMS _IOW(EPOLL_IOC_TYPE, 0x01, struct epoll_params)
+#define EPIOCGPARAMS _IOR(EPOLL_IOC_TYPE, 0x02, struct epoll_params)
__BEGIN_DECLS
diff --git a/libc/sysdeps/linux/common/utime.c b/libc/sysdeps/linux/common/utime.c
index e4ac0b269..c716388e8 100644
--- a/libc/sysdeps/linux/common/utime.c
+++ b/libc/sysdeps/linux/common/utime.c
@@ -9,7 +9,7 @@
#include <sys/syscall.h>
#include <utime.h>
-#if defined __NR_utimensat && !defined __NR_utime
+#if (defined(__NR_utimensat) || defined(__NR_utimensat_time64)) && !defined __NR_utime
# include <fcntl.h>
# include <stddef.h>
@@ -51,7 +51,7 @@ int utime(const char *file, const struct utimbuf *times)
}
#endif
-#if (defined __NR_utimensat && !defined __NR_utime) || \
+#if ((defined(__NR_utimensat) || defined(__NR_utimensat_time64)) && !defined __NR_utime) || \
defined __NR_utime || defined __NR_utimes
libc_hidden_def(utime)
#endif
diff --git a/libc/sysdeps/linux/common/utimensat.c b/libc/sysdeps/linux/common/utimensat.c
index fa6f90e55..5816c7890 100644
--- a/libc/sysdeps/linux/common/utimensat.c
+++ b/libc/sysdeps/linux/common/utimensat.c
@@ -8,6 +8,7 @@
#include <sys/syscall.h>
#include <sys/stat.h>
+#include <stdint.h>
#if defined(__UCLIBC_USE_TIME64__)
#include "internal/time64_helpers.h"
@@ -28,7 +29,7 @@ int utimensat(int fd, const char *path, const struct timespec times[2], int flag
}
};
- return INLINE_SYSCALL(utimensat_time64, 4, fd, path, times ? &__times64 : 0, flags);
+ return INLINE_SYSCALL(utimensat_time64, 4, fd, path, times ? (uintptr_t) &__times64 : 0, flags);
}
#else
_syscall4(int, utimensat, int, fd, const char *, path, const struct timespec *, times, int, flags)
diff --git a/libc/sysdeps/linux/csky/bits/uClibc_arch_features.h b/libc/sysdeps/linux/csky/bits/uClibc_arch_features.h
index 3f5dab80c..1b866cb90 100644
--- a/libc/sysdeps/linux/csky/bits/uClibc_arch_features.h
+++ b/libc/sysdeps/linux/csky/bits/uClibc_arch_features.h
@@ -17,9 +17,6 @@
/* can your target use syscall6() for mmap ? */
#undef __UCLIBC_MMAP_HAS_6_ARGS__
-/* does your target use statx */
-#define __UCLIBC_HAVE_STATX__
-
#ifdef __CSKYABIV2__
#undef __UCLIBC_SYSCALL_ALIGN_64BIT__
#else
diff --git a/libc/sysdeps/linux/nds32/Makefile.arch b/libc/sysdeps/linux/nds32/Makefile.arch
index c7627b847..caf163844 100644
--- a/libc/sysdeps/linux/nds32/Makefile.arch
+++ b/libc/sysdeps/linux/nds32/Makefile.arch
@@ -2,6 +2,6 @@
# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
CSRC-y := brk.c prctl.c mremap.c
-SSRC-y := setjmp.S __longjmp.S bsd-setjmp.S bsd-_setjmp.S clone.S sysdep.S
+SSRC-y := setjmp.S __longjmp.S bsd-setjmp.S bsd-_setjmp.S clone.S vfork.S sysdep.S
CSRC-$(UCLIBC_HAS_CONTEXT_FUNCS) += makecontext.c swapcontext.c
SSRC-$(UCLIBC_HAS_CONTEXT_FUNCS) += getcontext.S setcontext.S
diff --git a/libc/sysdeps/linux/nds32/bits/kernel_types.h b/libc/sysdeps/linux/nds32/bits/kernel_types.h
index 6b142d2e5..1b6ae4d1b 100644
--- a/libc/sysdeps/linux/nds32/bits/kernel_types.h
+++ b/libc/sysdeps/linux/nds32/bits/kernel_types.h
@@ -14,13 +14,13 @@
typedef unsigned short __kernel_dev_t;
typedef unsigned long __kernel_ino_t;
-typedef unsigned int __kernel_mode_t;
+typedef unsigned short __kernel_mode_t;
typedef unsigned short __kernel_nlink_t;
typedef long __kernel_off_t;
typedef int __kernel_pid_t;
-typedef int __kernel_ipc_pid_t;
-typedef unsigned int __kernel_uid_t;
-typedef unsigned int __kernel_gid_t;
+typedef unsigned short __kernel_ipc_pid_t;
+typedef unsigned short __kernel_uid_t;
+typedef unsigned short __kernel_gid_t;
typedef unsigned int __kernel_size_t;
typedef int __kernel_ssize_t;
typedef int __kernel_ptrdiff_t;
@@ -34,11 +34,19 @@ typedef unsigned short __kernel_gid16_t;
typedef unsigned int __kernel_uid32_t;
typedef unsigned int __kernel_gid32_t;
-typedef __kernel_uid_t __kernel_old_uid_t;
-typedef __kernel_gid_t __kernel_old_gid_t;
-typedef unsigned int __kernel_old_dev_t;
+typedef unsigned short __kernel_old_uid_t;
+typedef unsigned short __kernel_old_gid_t;
+typedef __kernel_dev_t __kernel_old_dev_t;
typedef long __kernel_long_t;
typedef unsigned long __kernel_ulong_t;
__extension__ typedef long long __kernel_loff_t;
+typedef struct {
+#ifdef __USE_ALL
+ int val[2];
+#else
+ int __val[2];
+#endif
+} __kernel_fsid_t;
+
#endif /* __ARCH_NDS32_POSIX_TYPES_H */
diff --git a/libc/sysdeps/linux/nds32/bits/syscalls.h b/libc/sysdeps/linux/nds32/bits/syscalls.h
index 50e30db7d..a5cdda18a 100644
--- a/libc/sysdeps/linux/nds32/bits/syscalls.h
+++ b/libc/sysdeps/linux/nds32/bits/syscalls.h
@@ -37,7 +37,8 @@
#define Y(x) X(x)
#define LIB_SYSCALL __NR_syscall
-#define __issue_syscall(syscall_name) "syscall 0x0;\n"
+#define __issue_syscall(syscall_name) \
+" syscall " Y(syscall_name) "; \n"
#undef INTERNAL_SYSCALL_ERROR_P
#define INTERNAL_SYSCALL_ERROR_P(val, err) ((unsigned int) (val) >= 0xfffff001u)
diff --git a/libc/sysdeps/linux/nds32/jmpbuf-unwind.h b/libc/sysdeps/linux/nds32/jmpbuf-unwind.h
index 8499e99b4..5b85f4d23 100644
--- a/libc/sysdeps/linux/nds32/jmpbuf-unwind.h
+++ b/libc/sysdeps/linux/nds32/jmpbuf-unwind.h
@@ -20,7 +20,7 @@
static inline uintptr_t __attribute__ ((unused))
_jmpbuf_sp (__jmp_buf regs)
{
- uintptr_t sp = &(regs)[0].__regs[__JMP_BUF_SP];
+ uintptr_t sp = (uintptr_t) &(regs)[0].__regs[__JMP_BUF_SP];
return sp;
}
diff --git a/libc/sysdeps/linux/nds32/sys/ucontext.h b/libc/sysdeps/linux/nds32/sys/ucontext.h
index ea86a3ad0..0d7422aab 100644
--- a/libc/sysdeps/linux/nds32/sys/ucontext.h
+++ b/libc/sysdeps/linux/nds32/sys/ucontext.h
@@ -36,10 +36,10 @@ typedef struct sigcontext mcontext_t;
/* Userlevel context. */
-typedef struct ucontext_t
+typedef struct ucontext
{
- unsigned long int __uc_flags;
- struct ucontext_t *uc_link;
+ unsigned long int uc_flags;
+ struct ucontext *uc_link;
stack_t uc_stack;
mcontext_t uc_mcontext;
__sigset_t uc_sigmask;
diff --git a/libc/sysdeps/linux/nds32/vfork.S b/libc/sysdeps/linux/nds32/vfork.S
new file mode 100644
index 000000000..ab32135fc
--- /dev/null
+++ b/libc/sysdeps/linux/nds32/vfork.S
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2016-2017 Andes Technology, Inc.
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+/* Copyright (C) 1999, 2002, 2003 Free Software Foundation, Inc.
+ Contributed by Philip Blundell <philb@gnu.org>.
+
+ 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>
+#define _ERRNO_H 1
+#include <bits/errno.h>
+
+/* Clone the calling process, but without copying the whole address space.
+ The calling process is suspended until the new process exits or is
+ replaced by a call to `execve'. Return -1 for errors, 0 to the new process,
+ and the process ID of the new process to the old process. */
+
+ENTRY (__vfork)
+#ifdef PIC
+.pic
+#endif
+
+#ifdef __NR_vfork
+ syscall __NR_vfork
+ bltz $r0, 2f
+1:
+ ret
+2:
+ sltsi $r1, $r0, -4096
+ bnez $r1, 1b;
+
+# ifdef __ASSUME_VFORK_SYSCALL
+# ifdef PIC
+ pushm $gp, $lp
+ cfi_adjust_cfa_offset(8)
+ cfi_rel_offset(gp, 0)
+ cfi_rel_offset(lp, 4)
+ mfusr $r15, $PC
+ sethi $gp, hi20(_GLOBAL_OFFSET_TABLE_+4)
+ ori $gp, $gp, lo12(_GLOBAL_OFFSET_TABLE_+8)
+ add $gp, $gp, $r15
+
+ ! r15=C_SYMBOL_NAME(__syscall_error)@PLT
+ sethi $r15, hi20(C_SYMBOL_NAME(__syscall_error)@PLT)
+ ori $r15, $r15, lo12(C_SYMBOL_NAME(__syscall_error)@PLT)
+ add $r15, $r15, $gp
+
+ ! jump to SYSCALL_ERROR
+ jral $r15
+ popm $gp, $lp
+ cfi_adjust_cfa_offset(-8)
+ cfi_restore(lp)
+ cfi_restore(gp)
+ ret
+# else
+ j C_SYMBOL_NAME(__syscall_error)
+# endif
+# else
+ /* Check if vfork syscall is known at all. */
+ li $r1, -ENOSYS
+ beq $r0, $r1, 1f
+
+# ifdef PIC
+3:
+ pushm $gp, $lp
+ cfi_adjust_cfa_offset(8)
+ cfi_rel_offset(gp, 0)
+ cfi_rel_offset(lp, 4)
+ mfusr $r15, $PC
+ sethi $gp, hi20(_GLOBAL_OFFSET_TABLE_+4)
+ ori $gp, $gp, lo12(_GLOBAL_OFFSET_TABLE_+8)
+ add $gp, $gp, $r15
+
+ ! r15=C_SYMBOL_NAME(__syscall_error)@PLT
+ sethi $r15, hi20(C_SYMBOL_NAME(__syscall_error)@PLT)
+ ori $r15, $r15, lo12(C_SYMBOL_NAME(__syscall_error)@PLT)
+ add $r15, $r15, $gp
+
+ ! jump to SYSCALL_ERROR
+ jral $r15
+ popm $gp, $lp
+ cfi_adjust_cfa_offset(-8)
+ cfi_restore(lp)
+ cfi_restore(gp)
+ ret
+# else
+ j C_SYMBOL_NAME(__syscall_error)
+# endif
+1:
+# endif
+#endif
+
+#ifndef __ASSUME_VFORK_SYSCALL
+ /* If we don't have vfork, fork is close enough. */
+ syscall __NR_fork
+ bgez $r0, 1f
+ sltsi $r1, $r0, -4096
+ bnez $r1, 1f
+
+# ifdef PIC
+ b 3b
+# else
+ j C_SYMBOL_NAME(__syscall_error)
+# endif
+1:
+ ret
+
+#elif !defined __NR_vfork
+# error "__NR_vfork not available and __ASSUME_VFORK_SYSCALL defined"
+#endif
+
+PSEUDO_END (__vfork)
+weak_alias (__vfork, vfork)
+libc_hidden_def (vfork)
diff --git a/libc/sysdeps/linux/riscv32/sys/ucontext.h b/libc/sysdeps/linux/riscv32/sys/ucontext.h
index 2893ff359..308ccb8c2 100644
--- a/libc/sysdeps/linux/riscv32/sys/ucontext.h
+++ b/libc/sysdeps/linux/riscv32/sys/ucontext.h
@@ -83,10 +83,10 @@ typedef struct mcontext_t
} mcontext_t;
/* Userlevel context. */
-typedef struct ucontext_t
+typedef struct ucontext
{
unsigned long int __uc_flags;
- struct ucontext_t *uc_link;
+ struct ucontext *uc_link;
stack_t uc_stack;
sigset_t uc_sigmask;
/* There's some padding here to allow sigset_t to be expanded in the
diff --git a/libc/sysdeps/linux/riscv64/sys/ucontext.h b/libc/sysdeps/linux/riscv64/sys/ucontext.h
index 2893ff359..308ccb8c2 100644
--- a/libc/sysdeps/linux/riscv64/sys/ucontext.h
+++ b/libc/sysdeps/linux/riscv64/sys/ucontext.h
@@ -83,10 +83,10 @@ typedef struct mcontext_t
} mcontext_t;
/* Userlevel context. */
-typedef struct ucontext_t
+typedef struct ucontext
{
unsigned long int __uc_flags;
- struct ucontext_t *uc_link;
+ struct ucontext *uc_link;
stack_t uc_stack;
sigset_t uc_sigmask;
/* There's some padding here to allow sigset_t to be expanded in the
diff --git a/libc/sysdeps/linux/sparc64/Makefile.arch b/libc/sysdeps/linux/sparc64/Makefile.arch
index 37b539b3b..cc4000b78 100644
--- a/libc/sysdeps/linux/sparc64/Makefile.arch
+++ b/libc/sysdeps/linux/sparc64/Makefile.arch
@@ -5,7 +5,7 @@
CSRC-y := __syscall_error.c sigaction.c
SSRC-y := __longjmp.S setjmp.S bsd-setjmp.S bsd-_setjmp.S brk.S fork.S \
- syscall.S pipe.S vfork.S clone.S
+ syscall.S pipe.S vfork.S clone.S sigreturn_stub.S
CSRC-y += $(addprefix soft-fp/, \
qp_add.c qp_cmp.c qp_cmpe.c qp_div.c qp_dtoq.c qp_feq.c qp_fge.c \
diff --git a/libc/sysdeps/linux/sparc64/sigaction.c b/libc/sysdeps/linux/sparc64/sigaction.c
index d8aaad0fb..b28fa659a 100644
--- a/libc/sysdeps/linux/sparc64/sigaction.c
+++ b/libc/sysdeps/linux/sparc64/sigaction.c
@@ -26,7 +26,7 @@
/* SPARC 64bit userland requires a kernel that has rt signals anyway. */
-static void __rt_sigreturn_stub (void);
+void __rt_sigreturn_stub (void);
int __libc_sigaction (int sig, const struct sigaction *act, struct sigaction *oact)
{
@@ -67,11 +67,3 @@ libc_hidden_weak(sigaction)
# endif
#endif
-static void
-__rt_sigreturn_stub (void)
-{
- __asm__ ("mov %0, %%g1\n\t"
- "ta 0x6d\n\t"
- : /* no outputs */
- : "i" (__NR_rt_sigreturn));
-}
diff --git a/libc/sysdeps/linux/sparc64/sigreturn_stub.S b/libc/sysdeps/linux/sparc64/sigreturn_stub.S
new file mode 100644
index 000000000..a5c9bb47f
--- /dev/null
+++ b/libc/sysdeps/linux/sparc64/sigreturn_stub.S
@@ -0,0 +1,10 @@
+#include <sysdep.h>
+
+ nop
+ nop
+
+ENTRY_NOCFI (__rt_sigreturn_stub)
+ mov __NR_rt_sigreturn, %g1
+ ta 0x6d
+END_NOCFI (__rt_sigreturn_stub)
+
diff --git a/libc/sysdeps/linux/sparc64/sysdep.h b/libc/sysdeps/linux/sparc64/sysdep.h
index 31008c34b..5a4c36348 100644
--- a/libc/sysdeps/linux/sparc64/sysdep.h
+++ b/libc/sysdeps/linux/sparc64/sysdep.h
@@ -83,6 +83,15 @@ C_LABEL(name) \
cfi_endproc; \
.size name, . - name
+#define ENTRY_NOCFI(name) \
+ .align 4; \
+ .global C_SYMBOL_NAME(name); \
+ .type name, @function; \
+C_LABEL(name)
+
+#define END_NOCFI(name) \
+ .size name, . - name
+
#define LOC(name) .L##name
#undef PSEUDO
diff --git a/libc/sysdeps/linux/tile/sys/ucontext.h b/libc/sysdeps/linux/tile/sys/ucontext.h
index ed2c27b58..068da8c4a 100644
--- a/libc/sysdeps/linux/tile/sys/ucontext.h
+++ b/libc/sysdeps/linux/tile/sys/ucontext.h
@@ -82,10 +82,10 @@ typedef struct
} mcontext_t;
/* Userlevel context. */
-typedef struct ucontext_t
+typedef struct ucontext
{
unsigned long int __ctx(uc_flags);
- struct ucontext_t *uc_link;
+ struct ucontext *uc_link;
stack_t uc_stack;
mcontext_t uc_mcontext;
sigset_t uc_sigmask;
diff --git a/libc/sysdeps/linux/xtensa/__start_context.S b/libc/sysdeps/linux/xtensa/__start_context.S
index a30d7b618..e6ce93347 100644
--- a/libc/sysdeps/linux/xtensa/__start_context.S
+++ b/libc/sysdeps/linux/xtensa/__start_context.S
@@ -22,9 +22,10 @@
* There's no entry instruction, makecontext sets up ucontext_t as if
* getcontext was called above and is about to return here.
* Registers on entry to this function:
- * a12: func to call
+ * a12: func to call (function descriptor in case of FDPIC)
* a13: ucp->uc_link, next context to activate if func returns
* a14: func argc
+ * a15: current GOT pointer (in case of FDPIC)
*/
.literal_position
@@ -46,14 +47,17 @@ ENTRY_PREFIX(__start_context)
addi a1, a1, 16
/* func arguments 6..argc - 1 are now at the top of the stack */
1:
+ FDPIC_LOAD_FUNCDESC (a12, a12)
callx0 a12
beqz a13, 1f
mov a2, a13
movi a4, JUMPTARGET (setcontext)
+ FDPIC_LOAD_JUMPTARGET (a4, a15, a4)
callx0 a4
1:
movi a4, JUMPTARGET (_exit)
movi a2, 0
+ FDPIC_LOAD_JUMPTARGET (a4, a15, a4)
callx0 a4
ill
END(__start_context)
diff --git a/libc/sysdeps/linux/xtensa/bits/elf-fdpic.h b/libc/sysdeps/linux/xtensa/bits/elf-fdpic.h
new file mode 100644
index 000000000..19bb247b8
--- /dev/null
+++ b/libc/sysdeps/linux/xtensa/bits/elf-fdpic.h
@@ -0,0 +1,117 @@
+/* Copyright 2003, 2004 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.
+
+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.)
+
+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
+Library 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; see the file COPYING.LIB. If
+not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef _BITS_ELF_FDPIC_H
+#define _BITS_ELF_FDPIC_H
+
+/* These data structures are described in the FDPIC ABI extension.
+ The kernel passes a process a memory map, such that for every LOAD
+ segment there is an elf32_fdpic_loadseg entry. A pointer to an
+ elf32_fdpic_loadmap is passed in r7 at start-up, and a pointer to
+ an additional such map is passed in r8 for the interpreter, when
+ there is one. */
+
+#include <elf.h>
+
+/* This data structure represents a PT_LOAD segment. */
+struct elf32_fdpic_loadseg
+{
+ /* Core address to which the segment is mapped. */
+ Elf32_Addr addr;
+ /* VMA recorded in the program header. */
+ Elf32_Addr p_vaddr;
+ /* Size of this segment in memory. */
+ Elf32_Word p_memsz;
+};
+
+struct elf32_fdpic_loadmap {
+ /* Protocol version number, must be zero. */
+ Elf32_Half version;
+ /* Number of segments in this map. */
+ Elf32_Half nsegs;
+ /* The actual memory map. */
+ struct elf32_fdpic_loadseg segs[/*nsegs*/];
+};
+
+struct elf32_fdpic_loadaddr {
+ struct elf32_fdpic_loadmap *map;
+ void *got_value;
+};
+
+/* Map a pointer's VMA to its corresponding address according to the
+ load map. */
+static __always_inline void *
+__reloc_pointer (void *p,
+ const struct elf32_fdpic_loadmap *map)
+{
+ int c;
+
+#if 0
+ if (map->version != 0)
+ /* Crash. */
+ ((void(*)())0)();
+#endif
+
+ /* No special provision is made for NULL. We don't want NULL
+ addresses to go through relocation, so they shouldn't be in
+ .rofixup sections, and, if they're present in dynamic
+ relocations, they shall be mapped to the NULL address without
+ undergoing relocations. */
+
+ for (c = 0;
+ /* Take advantage of the fact that the loadmap is ordered by
+ virtual addresses. In general there will only be 2 entries,
+ so it's not profitable to do a binary search. */
+ c < map->nsegs && p >= (void*)map->segs[c].p_vaddr;
+ c++)
+ {
+ /* This should be computed as part of the pointer comparison
+ above, but we want to use the carry in the comparison, so we
+ can't convert it to an integer type beforehand. */
+ unsigned long offset = (char*)p - (char*)map->segs[c].p_vaddr;
+ /* We only check for one-past-the-end for the last segment,
+ assumed to be the data segment, because other cases are
+ ambiguous in the absence of padding between segments, and
+ rofixup already serves as padding between text and data.
+ Unfortunately, unless we special-case the last segment, we
+ fail to relocate the _end symbol. */
+ if (offset < map->segs[c].p_memsz
+ || (offset == map->segs[c].p_memsz && c + 1 == map->nsegs))
+ return (char*)map->segs[c].addr + offset;
+ }
+
+ /* We might want to crash instead. */
+ return (void*)-1;
+}
+
+# define __RELOC_POINTER(ptr, loadaddr) \
+ (__reloc_pointer ((void*)(ptr), \
+ (loadaddr).map))
+
+void*
+__self_reloc (const struct elf32_fdpic_loadmap *map, void ***p, void ***e);
+
+#endif /* _BITS_ELF_FDPIC_H */
diff --git a/libc/sysdeps/linux/xtensa/bits/xtensa-config.h b/libc/sysdeps/linux/xtensa/bits/xtensa-config.h
index b99928b1e..bfcd571d2 100644
--- a/libc/sysdeps/linux/xtensa/bits/xtensa-config.h
+++ b/libc/sysdeps/linux/xtensa/bits/xtensa-config.h
@@ -32,21 +32,41 @@
macros. */
#undef XCHAL_HAVE_NSA
+#ifdef __XCHAL_HAVE_NSA
+#define XCHAL_HAVE_NSA __XCHAL_HAVE_NSA
+#else
#define XCHAL_HAVE_NSA 1
+#endif
#undef XCHAL_HAVE_LOOPS
+#ifdef __XCHAL_HAVE_LOOPS
+#define XCHAL_HAVE_LOOPS __XCHAL_HAVE_LOOPS
+#else
#define XCHAL_HAVE_LOOPS 1
+#endif
/* Assume the maximum number of AR registers. This currently only affects
the __window_spill function, and it is always safe to flush extra. */
#undef XCHAL_NUM_AREGS
+#ifdef __XCHAL_NUM_AREGS
+#define XCHAL_NUM_AREGS __XCHAL_NUM_AREGS
+#else
#define XCHAL_NUM_AREGS 64
+#endif
#undef XCHAL_HAVE_S32C1I
+#ifdef __XCHAL_HAVE_S32C1I
+#define XCHAL_HAVE_S32C1I __XCHAL_HAVE_S32C1I
+#else
#define XCHAL_HAVE_S32C1I 1
+#endif
#undef XCHAL_HAVE_EXCLUSIVE
+#ifdef __XCHAL_HAVE_EXCLUSIVE
+#define XCHAL_HAVE_EXCLUSIVE __XCHAL_HAVE_EXCLUSIVE
+#else
#define XCHAL_HAVE_EXCLUSIVE 0
+#endif
#endif /* !XTENSA_CONFIG_H */
diff --git a/libc/sysdeps/linux/xtensa/clone.S b/libc/sysdeps/linux/xtensa/clone.S
index ebfdcc1f6..a11044cd0 100644
--- a/libc/sysdeps/linux/xtensa/clone.S
+++ b/libc/sysdeps/linux/xtensa/clone.S
@@ -81,11 +81,17 @@ ENTRY (__clone)
callx4 a2
#elif defined(__XTENSA_CALL0_ABI__)
mov a2, a9 /* load up the 'arg' parameter */
+#ifdef __FDPIC__
+ mov a12, a11
+ l32i a11, a7, 4
+ l32i a7, a7, 0
+#endif
callx0 a7 /* call the user's function */
/* Call _exit. Note that any return parameter from the user's
function in a2 is seen as inputs to _exit. */
movi a0, JUMPTARGET(_exit)
+ FDPIC_LOAD_JUMPTARGET(a0, a12, a0)
callx0 a0
#else
#error Unsupported Xtensa ABI
diff --git a/libc/sysdeps/linux/xtensa/crt1.S b/libc/sysdeps/linux/xtensa/crt1.S
index 3fa14ae58..a12f82dd6 100644
--- a/libc/sysdeps/linux/xtensa/crt1.S
+++ b/libc/sysdeps/linux/xtensa/crt1.S
@@ -35,6 +35,86 @@
#include <features.h>
+#if defined(__FDPIC__)
+
+/* This is the canonical entry point, usually the first thing in the text
+ segment. When the entry point runs, most register values are unspecified,
+ except for:
+
+ a6 Address of .dynamic section
+ a5 Interpreter map
+ a4 Executable map
+
+ a2 Contains a function pointer to be registered with `atexit'.
+ This is how the dynamic linker arranges to have DT_FINI
+ functions called for shared libraries that have been loaded
+ before this code runs.
+
+ a1 The stack (i.e., a1+16) contains the arguments and environment:
+ a1+0 argc
+ a1+4 argv[0]
+ ...
+ a1+(4*argc) NULL
+ a1+(4*(argc+1)) envp[0]
+ ...
+ NULL
+ */
+ .text
+ .align 4
+ .literal_position
+ .global _start
+ .type _start, @function
+_start:
+#if defined(__XTENSA_CALL0_ABI__)
+
+ .begin no-transform
+ call0 1f
+2:
+ .end no-transform
+ .align 4
+ .literal_position
+1:
+ movi a15, 2b
+ sub a15, a0, a15
+
+ mov a12, a4
+ mov a13, a5
+ mov a14, a6
+ mov a2, a4
+ movi a3, __ROFIXUP_LIST__
+ add a3, a3, a15
+ movi a4, __ROFIXUP_END__
+ add a4, a4, a15
+ movi a0, __self_reloc
+ add a0, a0, a15
+ callx0 a0
+
+ mov a11, a2
+ movi a2, main@GOTOFFFUNCDESC
+ add a2, a2, a11
+ l32i a3, sp, 0 /* argc */
+ addi a4, sp, 4 /* argv */
+ /* a5 is either 0 when static or set by the RTLD to the rtld_fini */
+ mov a7, a13
+ /* unused stack_end argument is what used to be argc */
+ movi a5, _init@GOTOFFFUNCDESC
+ add a5, a5, a11
+ movi a6, _fini@GOTOFFFUNCDESC
+ add a6, a6, a11
+
+ movi a0, __uClibc_main@GOTOFFFUNCDESC
+ add a0, a0, a11
+ l32i a11, a0, 4
+ l32i a0, a0, 0
+ callx0 a0
+ ill
+
+#else
+#error Unsupported Xtensa ABI
+#endif
+
+#else /* defined(__FDPIC__) */
+
#ifndef __UCLIBC_CTOR_DTOR__
.weak _init
.weak _fini
@@ -173,3 +253,4 @@ __data_start:
.long 0
.weak data_start
data_start = __data_start
+#endif /* defined(__FDPIC__) */
diff --git a/libc/sysdeps/linux/xtensa/crti.S b/libc/sysdeps/linux/xtensa/crti.S
index ba804eb45..2923ff09d 100644
--- a/libc/sysdeps/linux/xtensa/crti.S
+++ b/libc/sysdeps/linux/xtensa/crti.S
@@ -3,6 +3,7 @@
.section .init
.align 4
.global _init
+ .hidden _init
.type _init, @function
_init:
#if defined(__XTENSA_WINDOWED_ABI__)
@@ -10,6 +11,10 @@ _init:
#elif defined(__XTENSA_CALL0_ABI__)
addi sp, sp, -16
s32i a0, sp, 0
+#ifdef __FDPIC__
+ s32i a12, sp, 4
+ mov a12, a11
+#endif
#else
#error Unsupported Xtensa ABI
#endif
@@ -17,6 +22,7 @@ _init:
.section .fini
.align 4
.global _fini
+ .hidden _fini
.type _fini, @function
_fini:
#if defined(__XTENSA_WINDOWED_ABI__)
@@ -24,6 +30,10 @@ _fini:
#elif defined(__XTENSA_CALL0_ABI__)
addi sp, sp, -16
s32i a0, sp, 0
+#ifdef __FDPIC__
+ s32i a12, sp, 4
+ mov a12, a11
+#endif
#else
#error Unsupported Xtensa ABI
#endif
diff --git a/libc/sysdeps/linux/xtensa/crtn.S b/libc/sysdeps/linux/xtensa/crtn.S
index a3598da1a..6f797e8bd 100644
--- a/libc/sysdeps/linux/xtensa/crtn.S
+++ b/libc/sysdeps/linux/xtensa/crtn.S
@@ -4,6 +4,9 @@
#if defined(__XTENSA_WINDOWED_ABI__)
retw
#elif defined(__XTENSA_CALL0_ABI__)
+#ifdef __FDPIC__
+ l32i a12, sp, 4
+#endif
l32i a0, sp, 0
addi sp, sp, 16
ret
@@ -15,6 +18,9 @@
#if defined(__XTENSA_WINDOWED_ABI__)
retw
#elif defined(__XTENSA_CALL0_ABI__)
+#ifdef __FDPIC__
+ l32i a12, sp, 4
+#endif
l32i a0, sp, 0
addi sp, sp, 16
ret
diff --git a/libc/sysdeps/linux/xtensa/crtreloc.c b/libc/sysdeps/linux/xtensa/crtreloc.c
new file mode 100644
index 000000000..697ef91ab
--- /dev/null
+++ b/libc/sysdeps/linux/xtensa/crtreloc.c
@@ -0,0 +1,105 @@
+/* Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+ written by Alexandre Oliva <aoliva@redhat.com>
+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.
+
+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.)
+
+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
+Library 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; see the file COPYING.LIB. If
+not, see <http://www.gnu.org/licenses/>. */
+
+#ifdef __FDPIC__
+
+#include <sys/types.h>
+#include <link.h>
+
+/* This file is to be compiled into crt object files, to enable
+ executables to easily self-relocate. */
+
+/* Compute the runtime address of pointer in the range [p,e), and then
+ map the pointer pointed by it. */
+static __always_inline void ***
+reloc_range_indirect (void ***p, void ***e,
+ const struct elf32_fdpic_loadmap *map)
+{
+ while (p < e)
+ {
+ if (*p != (void **)-1)
+ {
+ void *ptr = __reloc_pointer (*p, map);
+
+ if (ptr != (void *)-1)
+ {
+ unsigned long off = ((unsigned long)ptr & 3) * 8;
+ unsigned long *pa = (unsigned long *)((unsigned long)ptr & -4);
+ unsigned long v2;
+ void *pt;
+
+ if (off)
+ {
+ unsigned long v0, v1;
+#ifdef __XTENSA_EB__
+ v0 = pa[1]; v1 = pa[0];
+ v2 = (v1 >> (32 - off)) | (v0 << off);
+#else /* __XTENSA_EL__ */
+ v0 = pa[0]; v1 = pa[1];
+ v2 = (v0 << (32 - off)) | (v1 >> off);
+#endif
+ pt = (void *)((v1 << (32 - off)) | (v0 >> off));
+ }
+ else
+ pt = *(void**)ptr;
+ pt = __reloc_pointer (pt, map);
+ if (off)
+ {
+ unsigned long v = (unsigned long)pt;
+#ifdef __XTENSA_EB__
+ pa[0] = (v2 << (32 - off)) | (v >> off);
+ pa[1] = (v << (32 - off)) | (v2 >> off);
+#else /* __XTENSA_EL__ */
+ pa[0] = (v2 >> (32 - off)) | (v << off);
+ pa[1] = (v >> (32 - off)) | (v2 << off);
+#endif
+ }
+ else
+ *(void**)ptr = pt;
+ }
+ }
+ p++;
+ }
+ return p;
+}
+
+/* Call __reloc_range_indirect for the given range except for the last
+ entry, whose contents are only relocated. It's expected to hold
+ the GOT value. */
+attribute_hidden void*
+__self_reloc (const struct elf32_fdpic_loadmap *map,
+ void ***p, void ***e)
+{
+ p = reloc_range_indirect (p, e-1, map);
+
+ if (p >= e)
+ return (void*)-1;
+
+ return __reloc_pointer (*p, map);
+}
+
+#endif /* __FDPIC__ */
diff --git a/libc/sysdeps/linux/xtensa/getcontext.S b/libc/sysdeps/linux/xtensa/getcontext.S
index 7588a91b3..4cc644552 100644
--- a/libc/sysdeps/linux/xtensa/getcontext.S
+++ b/libc/sysdeps/linux/xtensa/getcontext.S
@@ -33,6 +33,7 @@ ENTRY(__getcontext)
addi a4, a2, UCONTEXT_SIGMASK
movi a2, SIG_BLOCK
movi a5, JUMPTARGET (sigprocmask)
+ FDPIC_LOAD_JUMPTARGET (a5, a11, a5)
jx a5
END(__getcontext)
#elif defined(__XTENSA_WINDOWED_ABI__)
diff --git a/libc/sysdeps/linux/xtensa/makecontext.c b/libc/sysdeps/linux/xtensa/makecontext.c
index da26a0130..0a8f7116f 100644
--- a/libc/sysdeps/linux/xtensa/makecontext.c
+++ b/libc/sysdeps/linux/xtensa/makecontext.c
@@ -73,7 +73,12 @@ __makecontext (ucontext_t *ucp, void (*func) (void), int argc, ...)
sp -= 4 * (argc + 2);
sp &= -16;
+#ifdef __FDPIC__
+ ucp->uc_mcontext.sc_pc = ((unsigned long *) __start_context)[0];
+ ucp->uc_mcontext.sc_a[15] = ((unsigned long *) __start_context)[1];
+#else
ucp->uc_mcontext.sc_pc = (unsigned long) __start_context;
+#endif
ucp->uc_mcontext.sc_a[1] = sp;
ucp->uc_mcontext.sc_a[12] = (unsigned long) func;
ucp->uc_mcontext.sc_a[13] = (unsigned long) ucp->uc_link;
diff --git a/libc/sysdeps/linux/xtensa/setcontext.S b/libc/sysdeps/linux/xtensa/setcontext.S
index 4df7cc049..72915ef8d 100644
--- a/libc/sysdeps/linux/xtensa/setcontext.S
+++ b/libc/sysdeps/linux/xtensa/setcontext.S
@@ -28,6 +28,7 @@ ENTRY(__setcontext)
movi a4, 0
movi a2, SIG_SETMASK
movi a5, JUMPTARGET (sigprocmask)
+ FDPIC_LOAD_JUMPTARGET (a5, a11, a5)
callx0 a5
bnez a2, .Lerror
diff --git a/libc/sysdeps/linux/xtensa/setjmp.S b/libc/sysdeps/linux/xtensa/setjmp.S
index b8152fdd8..d629c11a8 100644
--- a/libc/sysdeps/linux/xtensa/setjmp.S
+++ b/libc/sysdeps/linux/xtensa/setjmp.S
@@ -155,7 +155,8 @@ ENTRY (__sigsetjmp)
s32i a14, a2, 16
s32i a15, a2, 20
mov a12, a2
- movi a0, __sigjmp_save
+ movi a0, JUMPTARGET(__sigjmp_save)
+ FDPIC_LOAD_JUMPTARGET(a0, a11, a0)
callx0 a0
l32i a0, a12, 0
l32i a12, a12, 8
diff --git a/libc/sysdeps/linux/xtensa/swapcontext.S b/libc/sysdeps/linux/xtensa/swapcontext.S
index a215edc6d..40b38e98c 100644
--- a/libc/sysdeps/linux/xtensa/swapcontext.S
+++ b/libc/sysdeps/linux/xtensa/swapcontext.S
@@ -36,6 +36,7 @@ ENTRY(__swapcontext)
addi a4, a2, UCONTEXT_SIGMASK
movi a2, SIG_SETMASK
movi a5, JUMPTARGET (sigprocmask)
+ FDPIC_LOAD_JUMPTARGET (a5, a11, a5)
callx0 a5
bnez a2, .Lerror
diff --git a/libc/sysdeps/linux/xtensa/sysdep.h b/libc/sysdeps/linux/xtensa/sysdep.h
index 80b3f30fc..d05741027 100644
--- a/libc/sysdeps/linux/xtensa/sysdep.h
+++ b/libc/sysdeps/linux/xtensa/sysdep.h
@@ -75,13 +75,27 @@
#define LITERAL_POSITION .literal_position
#undef JUMPTARGET
-#ifdef __PIC__
+#if defined(__FDPIC__)
+#define JUMPTARGET(name) name##@GOTOFFFUNCDESC
+#define FDPIC_LOAD_FUNCDESC(call_target, funcdesc) \
+ l32i a11, funcdesc, 4; \
+ l32i call_target, funcdesc, 0
+
+#define FDPIC_LOAD_JUMPTARGET(call_target, got_base, jumptarget)\
+ add call_target, got_base, jumptarget; \
+ FDPIC_LOAD_FUNCDESC(call_target, call_target)
+
+#elif defined(__PIC__)
/* The "@PLT" suffix is currently a no-op for non-shared linking, but
it doesn't hurt to use it conditionally for PIC code in case that
changes someday. */
#define JUMPTARGET(name) name##@PLT
+#define FDPIC_LOAD_FUNCDESC(call_target, funcdesc)
+#define FDPIC_LOAD_JUMPTARGET(call_target, got_base, jumptarget)
#else
#define JUMPTARGET(name) name
+#define FDPIC_LOAD_FUNCDESC(call_target, funcdesc)
+#define FDPIC_LOAD_JUMPTARGET(call_target, got_base, jumptarget)
#endif
#ifndef FRAMESIZE
@@ -153,6 +167,21 @@
#if defined _LIBC_REENTRANT
# if defined USE___THREAD
+#ifdef __FDPIC__
+# define SYSCALL_ERROR_ERRNO errno
+# define SYSCALL_ERROR_HANDLER \
+0: rur a4, THREADPTR; \
+ movi a3, SYSCALL_ERROR_ERRNO@GOTTPOFF; \
+ .reloc ., R_XTENSA_TLS_TPOFF_PTR, SYSCALL_ERROR_ERRNO; \
+ add a3, a3, a11; \
+ .reloc ., R_XTENSA_TLS_TPOFF_LOAD, SYSCALL_ERROR_ERRNO; \
+ l32i a3, a3, 0; \
+ neg a2, a2; \
+ add a4, a4, a3; \
+ s32i a2, a4, 0; \
+ movi a2, -1; \
+ j .Lpseudo_end;
+#else
# define SYSCALL_ERROR_ERRNO errno
# define SYSCALL_ERROR_HANDLER \
0: rur a4, THREADPTR; \
@@ -162,13 +191,14 @@
s32i a2, a4, 0; \
movi a2, -1; \
j .Lpseudo_end;
+#endif
# else /* !USE___THREAD */
#if defined(__XTENSA_WINDOWED_ABI__)
# define SYSCALL_ERROR_HANDLER \
0: neg a2, a2; \
mov a6, a2; \
- movi a4, __errno_location@PLT; \
+ movi a4, JUMPTARGET(__errno_location); \
callx4 a4; \
s32i a2, a6, 0; \
movi a2, -1; \
@@ -179,7 +209,8 @@
addi a1, a1, -16; \
s32i a0, a1, 0; \
s32i a2, a1, 4; \
- movi a0, __errno_location@PLT; \
+ movi a0, JUMPTARGET(__errno_location); \
+ FDPIC_LOAD_JUMPTARGET(a0, a11, a0); \
callx0 a0; \
l32i a0, a1, 0; \
l32i a3, a1, 4; \
@@ -193,12 +224,23 @@
# endif /* !USE___THREAD */
#else /* !_LIBC_REENTRANT */
+#ifdef __FDPIC__
+#define SYSCALL_ERROR_HANDLER \
+0: movi a4, errno@GOT; \
+ add a4, a4, a11; \
+ l32i a4, a4, 0; \
+ neg a2, a2; \
+ s32i a2, a4, 0; \
+ movi a2, -1; \
+ j .Lpseudo_end;
+#else
#define SYSCALL_ERROR_HANDLER \
0: movi a4, errno; \
neg a2, a2; \
s32i a2, a4, 0; \
movi a2, -1; \
j .Lpseudo_end;
+#endif /* __FDPIC__ */
#endif /* _LIBC_REENTRANT */
#endif /* __ASSEMBLER__ */