summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Rules.mak6
-rw-r--r--extra/Configs/Config.aarch6432
-rw-r--r--extra/Configs/Config.in11
-rw-r--r--extra/Configs/Config.in.arch2
-rw-r--r--include/atomic.h10
-rw-r--r--include/elf.h166
-rw-r--r--ldso/include/dl-syscall.h10
-rw-r--r--ldso/ldso/aarch64/dl-startup.h98
-rw-r--r--ldso/ldso/aarch64/dl-syscalls.h1
-rw-r--r--ldso/ldso/aarch64/dl-sysdep.h107
-rw-r--r--ldso/ldso/aarch64/dl-tlsdesc.S207
-rw-r--r--ldso/ldso/aarch64/elfinterp.c306
-rw-r--r--ldso/ldso/aarch64/resolve.S97
-rw-r--r--libc/string/aarch64/Makefile13
-rw-r--r--libc/string/aarch64/memcpy.S230
-rw-r--r--libc/string/aarch64/memset.S189
-rw-r--r--libc/sysdeps/linux/aarch64/Makefile9
-rw-r--r--libc/sysdeps/linux/aarch64/Makefile.arch5
-rw-r--r--libc/sysdeps/linux/aarch64/__longjmp.S107
-rw-r--r--libc/sysdeps/linux/aarch64/__syscall_error.c18
-rw-r--r--libc/sysdeps/linux/aarch64/bits/atomic.h172
-rw-r--r--libc/sysdeps/linux/aarch64/bits/endian.h30
-rw-r--r--libc/sysdeps/linux/aarch64/bits/fcntl.h329
-rw-r--r--libc/sysdeps/linux/aarch64/bits/kernel_types.h42
-rw-r--r--libc/sysdeps/linux/aarch64/bits/setjmp.h33
-rw-r--r--libc/sysdeps/linux/aarch64/bits/stackinfo.h33
-rw-r--r--libc/sysdeps/linux/aarch64/bits/syscalls.h106
-rw-r--r--libc/sysdeps/linux/aarch64/bits/uClibc_arch_features.h38
-rwxr-xr-xlibc/sysdeps/linux/aarch64/bits/uClibc_page.h25
-rw-r--r--libc/sysdeps/linux/aarch64/bits/wordsize.h18
-rw-r--r--libc/sysdeps/linux/aarch64/bsd-_setjmp.S1
-rw-r--r--libc/sysdeps/linux/aarch64/bsd-setjmp.S1
-rw-r--r--libc/sysdeps/linux/aarch64/clone.S85
-rw-r--r--libc/sysdeps/linux/aarch64/crt1.S89
-rw-r--r--libc/sysdeps/linux/aarch64/crti.S59
-rw-r--r--libc/sysdeps/linux/aarch64/crtn.S46
-rw-r--r--libc/sysdeps/linux/aarch64/jmpbuf-offsets.h57
-rw-r--r--libc/sysdeps/linux/aarch64/jmpbuf-unwind.h34
-rw-r--r--libc/sysdeps/linux/aarch64/setjmp.S59
-rw-r--r--libc/sysdeps/linux/aarch64/sys/procfs.h123
-rw-r--r--libc/sysdeps/linux/aarch64/sys/ucontext.h53
-rw-r--r--libc/sysdeps/linux/aarch64/sys/user.h37
-rw-r--r--libc/sysdeps/linux/aarch64/syscall.S42
-rw-r--r--libc/sysdeps/linux/aarch64/sysdep.h150
-rw-r--r--libc/sysdeps/linux/aarch64/vfork.S37
-rw-r--r--libc/sysdeps/linux/common-generic/bits/stat.h49
-rw-r--r--libc/sysdeps/linux/common/fstat.c28
-rw-r--r--libc/sysdeps/linux/common/fstatat.c9
-rw-r--r--libc/sysdeps/linux/common/lstat.c9
-rw-r--r--libc/sysdeps/linux/common/lstat64.c14
-rw-r--r--libc/sysdeps/linux/common/stat.c8
-rw-r--r--libpthread/nptl/sysdeps/aarch64/Makefile.arch32
-rw-r--r--libpthread/nptl/sysdeps/aarch64/dl-tls.h55
-rw-r--r--libpthread/nptl/sysdeps/aarch64/libc-dl-tlsdesc.S1
-rw-r--r--libpthread/nptl/sysdeps/aarch64/libc-tls.c35
-rw-r--r--libpthread/nptl/sysdeps/aarch64/pthread_spin_lock.c65
-rw-r--r--libpthread/nptl/sysdeps/aarch64/pthread_spin_trylock.c26
-rw-r--r--libpthread/nptl/sysdeps/aarch64/pthreaddef.h34
-rw-r--r--libpthread/nptl/sysdeps/aarch64/tcb-offsets.sym6
-rw-r--r--libpthread/nptl/sysdeps/aarch64/tls.h149
-rw-r--r--libpthread/nptl/sysdeps/aarch64/tlsdesc.sym17
-rw-r--r--libpthread/nptl/sysdeps/unix/sysv/linux/aarch64/Makefile13
-rw-r--r--libpthread/nptl/sysdeps/unix/sysv/linux/aarch64/Makefile.arch14
-rw-r--r--libpthread/nptl/sysdeps/unix/sysv/linux/aarch64/bits/pthreadtypes.h174
-rw-r--r--libpthread/nptl/sysdeps/unix/sysv/linux/aarch64/bits/semaphore.h30
-rw-r--r--libpthread/nptl/sysdeps/unix/sysv/linux/aarch64/createthread.c21
-rw-r--r--libpthread/nptl/sysdeps/unix/sysv/linux/aarch64/fork.c11
-rw-r--r--libpthread/nptl/sysdeps/unix/sysv/linux/aarch64/lowlevellock.h323
-rw-r--r--libpthread/nptl/sysdeps/unix/sysv/linux/aarch64/pt-raise.c18
-rw-r--r--libpthread/nptl/sysdeps/unix/sysv/linux/aarch64/pthread_once.c90
-rw-r--r--libpthread/nptl/sysdeps/unix/sysv/linux/aarch64/sysdep-cancel.h132
-rw-r--r--utils/ldd.c5
72 files changed, 4606 insertions, 85 deletions
diff --git a/Rules.mak b/Rules.mak
index 8bd286354..f53c5817a 100644
--- a/Rules.mak
+++ b/Rules.mak
@@ -300,6 +300,7 @@ ifneq ($(TARGET_ARCH),sh)
ifneq ($(TARGET_ARCH),c6x)
ifneq ($(TARGET_ARCH),h8300)
ifneq ($(TARGET_ARCH),arc)
+ifneq ($(TARGET_ARCH),aarch64)
CPU_CFLAGS-y += -msoft-float
endif
endif
@@ -310,6 +311,11 @@ endif
endif
endif
endif
+endif
+
+ifeq ($(TARGET_ARCH),aarch64)
+CPU_CFLAGS-y += -ftls-model=initial-exec
+endif
$(eval $(call check-gcc-var,-std=gnu99))
CPU_CFLAGS-y += $(CFLAG_-std=gnu99)
diff --git a/extra/Configs/Config.aarch64 b/extra/Configs/Config.aarch64
new file mode 100644
index 000000000..cf1ce3b79
--- /dev/null
+++ b/extra/Configs/Config.aarch64
@@ -0,0 +1,32 @@
+#
+# For a description of the syntax of this configuration file,
+# see extra/config/Kconfig-language.txt
+#
+
+config TARGET_ARCH
+ string
+ default "aarch64"
+
+config FORCE_OPTIONS_FOR_ARCH
+ bool
+ default y
+ select ARCH_ANY_ENDIAN
+ select ARCH_HAS_MMU
+ select UCLIBC_HAS_FPU
+
+choice
+ prompt "MMU Page Size"
+ default CONFIG_AARCH64_PAGE_SIZE_4K
+
+config CONFIG_AARCH64_PAGE_SIZE_4K
+ bool "4KB"
+ help
+ Choose between 4k(default), 16k or 64k
+
+config CONFIG_AARCH64_PAGE_SIZE_16K
+ bool "16KB"
+
+config CONFIG_AARCH64_PAGE_SIZE_64K
+ bool "64KB"
+
+endchoice
diff --git a/extra/Configs/Config.in b/extra/Configs/Config.in
index b2cf977b7..850bd7d13 100644
--- a/extra/Configs/Config.in
+++ b/extra/Configs/Config.in
@@ -15,6 +15,7 @@ config VERSION
choice
prompt "Target Architecture"
+ default TARGET_aarch64 if DESIRED_TARGET_ARCH = "aarch64"
default TARGET_alpha if DESIRED_TARGET_ARCH = "alpha"
default TARGET_arc if DESIRED_TARGET_ARCH = "arc"
default TARGET_arm if DESIRED_TARGET_ARCH = "arm"
@@ -42,6 +43,9 @@ choice
help
The architecture of your target.
+config TARGET_aarch64
+ bool "aarch64"
+
config TARGET_alpha
bool "alpha"
@@ -124,6 +128,10 @@ endchoice
menu "Target Architecture Features and Options"
+if TARGET_aarch64
+source "extra/Configs/Config.aarch64"
+endif
+
if TARGET_alpha
source "extra/Configs/Config.alpha"
endif
@@ -500,7 +508,8 @@ config UCLIBC_HAS_LINUXTHREADS
bool "Linuxthreads"
# linuxthreads need nanosleep()
select UCLIBC_HAS_REALTIME
- depends on !TARGET_metag
+ depends on !TARGET_aarch64 && \
+ !TARGET_metag
help
If you want to compile uClibc with Linuxthreads support, then answer Y.
diff --git a/extra/Configs/Config.in.arch b/extra/Configs/Config.in.arch
index 37dd8bd74..a1a2a5f99 100644
--- a/extra/Configs/Config.in.arch
+++ b/extra/Configs/Config.in.arch
@@ -191,7 +191,7 @@ config UCLIBC_HAS_FENV
config UCLIBC_HAS_LONG_DOUBLE_MATH
bool "Enable long double support"
depends on DO_C99_MATH
- depends on TARGET_aarch64 || TARGET_alpha || TARGET_i386 || TARGET_ia64 || TARGET_m68k || TARGET_powerpc || TARGET_s390 || TARGET_sparc || TARGET_tile || TARGET_x86_64
+ depends on TARGET_alpha || TARGET_i386 || TARGET_ia64 || TARGET_m68k || TARGET_powerpc || TARGET_s390 || TARGET_sparc || TARGET_tile || TARGET_x86_64
default y
help
If you want the uClibc math library to contain the full set of C99
diff --git a/include/atomic.h b/include/atomic.h
index 3680d8714..267aff5d5 100644
--- a/include/atomic.h
+++ b/include/atomic.h
@@ -542,24 +542,18 @@
({ __typeof (x) __x; __asm__ ("" : "=r" (__x) : "0" (x)); __x; })
#endif
-/* This is equal to 1 iff the architecture supports 64b atomic operations. */
-#define __HAVE_64B_ATOMICS 0 /* TODO: not yet used - Add these to arch bits! */
-#ifndef __HAVE_64B_ATOMICS
-#error Unable to determine if 64-bit atomics are present.
-#endif
-
/* The following functions are a subset of the atomic operations provided by
C11. Usually, a function named atomic_OP_MO(args) is equivalent to C11's
atomic_OP_explicit(args, memory_order_MO); exceptions noted below. */
/* Each arch can request to use compiler built-ins for C11 atomics. If it
does, all atomics will be based on these. */
-#if 0 /* not yet used USE_ATOMIC_COMPILER_BUILTINS */
+#if defined USE_ATOMIC_COMPILER_BUILTINS
/* We require 32b atomic operations; some archs also support 64b atomic
operations. */
void __atomic_link_error (void);
-# if __HAVE_64B_ATOMICS == 1
+# if defined(__HAVE_64B_ATOMICS) && __HAVE_64B_ATOMICS
# define __atomic_check_size(mem) \
if ((sizeof (*mem) != 4) && (sizeof (*mem) != 8)) \
__atomic_link_error ();
diff --git a/include/elf.h b/include/elf.h
index 0f188e792..5312be97c 100644
--- a/include/elf.h
+++ b/include/elf.h
@@ -269,6 +269,7 @@ typedef struct
#define EM_TI_C6000 140
#define EM_NDS32 167 /* Andes Tech NDS32 */
#define EM_METAG 174 /* Imagination Technologies Meta */
+#define EM_AARCH64 183 /* ARM AARCH64 */
#define EM_MICROBLAZE 189 /* Xilinx Microblaze */
#define EM_ARCV2 195 /* ARCv2 Cores */
@@ -725,6 +726,31 @@ typedef struct
#define NT_LWPSTATUS 16 /* Contains copy of lwpstatus struct */
#define NT_LWPSINFO 17 /* Contains copy of lwpinfo struct */
#define NT_PRFPXREG 20 /* Contains copy of fprxregset struct*/
+#define NT_SIGINFO 0x53494749 /* Contains copy of siginfo_t,
+ size might increase */
+#define NT_FILE 0x46494c45 /* Contains information about mapped
+ files */
+#define NT_PRXFPREG 0x46e62b7f /* Contains copy of user_fxsr_struct */
+#define NT_PPC_VMX 0x100 /* PowerPC Altivec/VMX registers */
+#define NT_PPC_SPE 0x101 /* PowerPC SPE/EVR registers */
+#define NT_PPC_VSX 0x102 /* PowerPC VSX registers */
+#define NT_386_TLS 0x200 /* i386 TLS slots (struct user_desc) */
+#define NT_386_IOPERM 0x201 /* x86 io permission bitmap (1=deny) */
+#define NT_X86_XSTATE 0x202 /* x86 extended state using xsave */
+#define NT_S390_HIGH_GPRS 0x300 /* s390 upper register halves */
+#define NT_S390_TIMER 0x301 /* s390 timer register */
+#define NT_S390_TODCMP 0x302 /* s390 TOD clock comparator register */
+#define NT_S390_TODPREG 0x303 /* s390 TOD programmable register */
+#define NT_S390_CTRS 0x304 /* s390 control registers */
+#define NT_S390_PREFIX 0x305 /* s390 prefix register */
+#define NT_S390_LAST_BREAK 0x306 /* s390 breaking event address */
+#define NT_S390_SYSTEM_CALL 0x307 /* s390 system call restart data */
+#define NT_S390_TDB 0x308 /* s390 transaction diagnostic block */
+#define NT_ARM_VFP 0x400 /* ARM VFP/NEON registers */
+#define NT_ARM_TLS 0x401 /* ARM TLS register */
+#define NT_ARM_HW_BREAK 0x402 /* ARM hardware breakpoint registers */
+#define NT_ARM_HW_WATCH 0x403 /* ARM hardware watchpoint registers */
+#define NT_ARM_SYSTEM_CALL 0x404 /* ARM system call number */
/* Legal values for the note segment descriptor types for object files. */
@@ -2358,6 +2384,146 @@ typedef Elf32_Addr Elf32_Conflict;
/* Processor specific values for the Phdr p_type field. */
#define PT_ARM_EXIDX 0x70000001 /* .ARM.exidx segment */
+/* AArch64 relocs. */
+
+#define R_AARCH64_NONE 0 /* No relocation. */
+
+/* ILP32 AArch64 relocs. */
+#define R_AARCH64_P32_ABS32 1 /* Direct 32 bit. */
+#define R_AARCH64_P32_COPY 180 /* Copy symbol at runtime. */
+#define R_AARCH64_P32_GLOB_DAT 181 /* Create GOT entry. */
+#define R_AARCH64_P32_JUMP_SLOT 182 /* Create PLT entry. */
+#define R_AARCH64_P32_RELATIVE 183 /* Adjust by program base. */
+#define R_AARCH64_P32_TLS_DTPMOD 184 /* Module number, 32 bit. */
+#define R_AARCH64_P32_TLS_DTPREL 185 /* Module-relative offset, 32 bit. */
+#define R_AARCH64_P32_TLS_TPREL 186 /* TP-relative offset, 32 bit. */
+#define R_AARCH64_P32_TLSDESC 187 /* TLS Descriptor. */
+#define R_AARCH64_P32_IRELATIVE 188 /* STT_GNU_IFUNC relocation. */
+
+/* LP64 AArch64 relocs. */
+#define R_AARCH64_ABS64 257 /* Direct 64 bit. */
+#define R_AARCH64_ABS32 258 /* Direct 32 bit. */
+#define R_AARCH64_ABS16 259 /* Direct 16-bit. */
+#define R_AARCH64_PREL64 260 /* PC-relative 64-bit. */
+#define R_AARCH64_PREL32 261 /* PC-relative 32-bit. */
+#define R_AARCH64_PREL16 262 /* PC-relative 16-bit. */
+#define R_AARCH64_MOVW_UABS_G0 263 /* Dir. MOVZ imm. from bits 15:0. */
+#define R_AARCH64_MOVW_UABS_G0_NC 264 /* Likewise for MOVK; no check. */
+#define R_AARCH64_MOVW_UABS_G1 265 /* Dir. MOVZ imm. from bits 31:16. */
+#define R_AARCH64_MOVW_UABS_G1_NC 266 /* Likewise for MOVK; no check. */
+#define R_AARCH64_MOVW_UABS_G2 267 /* Dir. MOVZ imm. from bits 47:32. */
+#define R_AARCH64_MOVW_UABS_G2_NC 268 /* Likewise for MOVK; no check. */
+#define R_AARCH64_MOVW_UABS_G3 269 /* Dir. MOV{K,Z} imm. from 63:48. */
+#define R_AARCH64_MOVW_SABS_G0 270 /* Dir. MOV{N,Z} imm. from 15:0. */
+#define R_AARCH64_MOVW_SABS_G1 271 /* Dir. MOV{N,Z} imm. from 31:16. */
+#define R_AARCH64_MOVW_SABS_G2 272 /* Dir. MOV{N,Z} imm. from 47:32. */
+#define R_AARCH64_LD_PREL_LO19 273 /* PC-rel. LD imm. from bits 20:2. */
+#define R_AARCH64_ADR_PREL_LO21 274 /* PC-rel. ADR imm. from bits 20:0. */
+#define R_AARCH64_ADR_PREL_PG_HI21 275 /* Page-rel. ADRP imm. from 32:12. */
+#define R_AARCH64_ADR_PREL_PG_HI21_NC 276 /* Likewise; no overflow check. */
+#define R_AARCH64_ADD_ABS_LO12_NC 277 /* Dir. ADD imm. from bits 11:0. */
+#define R_AARCH64_LDST8_ABS_LO12_NC 278 /* Likewise for LD/ST; no check. */
+#define R_AARCH64_TSTBR14 279 /* PC-rel. TBZ/TBNZ imm. from 15:2. */
+#define R_AARCH64_CONDBR19 280 /* PC-rel. cond. br. imm. from 20:2. */
+#define R_AARCH64_JUMP26 282 /* PC-rel. B imm. from bits 27:2. */
+#define R_AARCH64_CALL26 283 /* Likewise for CALL. */
+#define R_AARCH64_LDST16_ABS_LO12_NC 284 /* Dir. ADD imm. from bits 11:1. */
+#define R_AARCH64_LDST32_ABS_LO12_NC 285 /* Likewise for bits 11:2. */
+#define R_AARCH64_LDST64_ABS_LO12_NC 286 /* Likewise for bits 11:3. */
+#define R_AARCH64_MOVW_PREL_G0 287 /* PC-rel. MOV{N,Z} imm. from 15:0. */
+#define R_AARCH64_MOVW_PREL_G0_NC 288 /* Likewise for MOVK; no check. */
+#define R_AARCH64_MOVW_PREL_G1 289 /* PC-rel. MOV{N,Z} imm. from 31:16. */
+#define R_AARCH64_MOVW_PREL_G1_NC 290 /* Likewise for MOVK; no check. */
+#define R_AARCH64_MOVW_PREL_G2 291 /* PC-rel. MOV{N,Z} imm. from 47:32. */
+#define R_AARCH64_MOVW_PREL_G2_NC 292 /* Likewise for MOVK; no check. */
+#define R_AARCH64_MOVW_PREL_G3 293 /* PC-rel. MOV{N,Z} imm. from 63:48. */
+#define R_AARCH64_LDST128_ABS_LO12_NC 299 /* Dir. ADD imm. from bits 11:4. */
+#define R_AARCH64_MOVW_GOTOFF_G0 300 /* GOT-rel. off. MOV{N,Z} imm. 15:0. */
+#define R_AARCH64_MOVW_GOTOFF_G0_NC 301 /* Likewise for MOVK; no check. */
+#define R_AARCH64_MOVW_GOTOFF_G1 302 /* GOT-rel. o. MOV{N,Z} imm. 31:16. */
+#define R_AARCH64_MOVW_GOTOFF_G1_NC 303 /* Likewise for MOVK; no check. */
+#define R_AARCH64_MOVW_GOTOFF_G2 304 /* GOT-rel. o. MOV{N,Z} imm. 47:32. */
+#define R_AARCH64_MOVW_GOTOFF_G2_NC 305 /* Likewise for MOVK; no check. */
+#define R_AARCH64_MOVW_GOTOFF_G3 306 /* GOT-rel. o. MOV{N,Z} imm. 63:48. */
+#define R_AARCH64_GOTREL64 307 /* GOT-relative 64-bit. */
+#define R_AARCH64_GOTREL32 308 /* GOT-relative 32-bit. */
+#define R_AARCH64_GOT_LD_PREL19 309 /* PC-rel. GOT off. load imm. 20:2. */
+#define R_AARCH64_LD64_GOTOFF_LO15 310 /* GOT-rel. off. LD/ST imm. 14:3. */
+#define R_AARCH64_ADR_GOT_PAGE 311 /* P-page-rel. GOT off. ADRP 32:12. */
+#define R_AARCH64_LD64_GOT_LO12_NC 312 /* Dir. GOT off. LD/ST imm. 11:3. */
+#define R_AARCH64_LD64_GOTPAGE_LO15 313 /* GOT-page-rel. GOT off. LD/ST 14:3 */
+#define R_AARCH64_TLSGD_ADR_PREL21 512 /* PC-relative ADR imm. 20:0. */
+#define R_AARCH64_TLSGD_ADR_PAGE21 513 /* page-rel. ADRP imm. 32:12. */
+#define R_AARCH64_TLSGD_ADD_LO12_NC 514 /* direct ADD imm. from 11:0. */
+#define R_AARCH64_TLSGD_MOVW_G1 515 /* GOT-rel. MOV{N,Z} 31:16. */
+#define R_AARCH64_TLSGD_MOVW_G0_NC 516 /* GOT-rel. MOVK imm. 15:0. */
+#define R_AARCH64_TLSLD_ADR_PREL21 517 /* Like 512; local dynamic model. */
+#define R_AARCH64_TLSLD_ADR_PAGE21 518 /* Like 513; local dynamic model. */
+#define R_AARCH64_TLSLD_ADD_LO12_NC 519 /* Like 514; local dynamic model. */
+#define R_AARCH64_TLSLD_MOVW_G1 520 /* Like 515; local dynamic model. */
+#define R_AARCH64_TLSLD_MOVW_G0_NC 521 /* Like 516; local dynamic model. */
+#define R_AARCH64_TLSLD_LD_PREL19 522 /* TLS PC-rel. load imm. 20:2. */
+#define R_AARCH64_TLSLD_MOVW_DTPREL_G2 523 /* TLS DTP-rel. MOV{N,Z} 47:32. */
+#define R_AARCH64_TLSLD_MOVW_DTPREL_G1 524 /* TLS DTP-rel. MOV{N,Z} 31:16. */
+#define R_AARCH64_TLSLD_MOVW_DTPREL_G1_NC 525 /* Likewise; MOVK; no check. */
+#define R_AARCH64_TLSLD_MOVW_DTPREL_G0 526 /* TLS DTP-rel. MOV{N,Z} 15:0. */
+#define R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC 527 /* Likewise; MOVK; no check. */
+#define R_AARCH64_TLSLD_ADD_DTPREL_HI12 528 /* DTP-rel. ADD imm. from 23:12. */
+#define R_AARCH64_TLSLD_ADD_DTPREL_LO12 529 /* DTP-rel. ADD imm. from 11:0. */
+#define R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC 530 /* Likewise; no ovfl. check. */
+#define R_AARCH64_TLSLD_LDST8_DTPREL_LO12 531 /* DTP-rel. LD/ST imm. 11:0. */
+#define R_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC 532 /* Likewise; no check. */
+#define R_AARCH64_TLSLD_LDST16_DTPREL_LO12 533 /* DTP-rel. LD/ST imm. 11:1. */
+#define R_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC 534 /* Likewise; no check. */
+#define R_AARCH64_TLSLD_LDST32_DTPREL_LO12 535 /* DTP-rel. LD/ST imm. 11:2. */
+#define R_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC 536 /* Likewise; no check. */
+#define R_AARCH64_TLSLD_LDST64_DTPREL_LO12 537 /* DTP-rel. LD/ST imm. 11:3. */
+#define R_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC 538 /* Likewise; no check. */
+#define R_AARCH64_TLSIE_MOVW_GOTTPREL_G1 539 /* GOT-rel. MOV{N,Z} 31:16. */
+#define R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC 540 /* GOT-rel. MOVK 15:0. */
+#define R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 541 /* Page-rel. ADRP 32:12. */
+#define R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC 542 /* Direct LD off. 11:3. */
+#define R_AARCH64_TLSIE_LD_GOTTPREL_PREL19 543 /* PC-rel. load imm. 20:2. */
+#define R_AARCH64_TLSLE_MOVW_TPREL_G2 544 /* TLS TP-rel. MOV{N,Z} 47:32. */
+#define R_AARCH64_TLSLE_MOVW_TPREL_G1 545 /* TLS TP-rel. MOV{N,Z} 31:16. */
+#define R_AARCH64_TLSLE_MOVW_TPREL_G1_NC 546 /* Likewise; MOVK; no check. */
+#define R_AARCH64_TLSLE_MOVW_TPREL_G0 547 /* TLS TP-rel. MOV{N,Z} 15:0. */
+#define R_AARCH64_TLSLE_MOVW_TPREL_G0_NC 548 /* Likewise; MOVK; no check. */
+#define R_AARCH64_TLSLE_ADD_TPREL_HI12 549 /* TP-rel. ADD imm. 23:12. */
+#define R_AARCH64_TLSLE_ADD_TPREL_LO12 550 /* TP-rel. ADD imm. 11:0. */
+#define R_AARCH64_TLSLE_ADD_TPREL_LO12_NC 551 /* Likewise; no ovfl. check. */
+#define R_AARCH64_TLSLE_LDST8_TPREL_LO12 552 /* TP-rel. LD/ST off. 11:0. */
+#define R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC 553 /* Likewise; no ovfl. check. */
+#define R_AARCH64_TLSLE_LDST16_TPREL_LO12 554 /* TP-rel. LD/ST off. 11:1. */
+#define R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC 555 /* Likewise; no check. */
+#define R_AARCH64_TLSLE_LDST32_TPREL_LO12 556 /* TP-rel. LD/ST off. 11:2. */
+#define R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC 557 /* Likewise; no check. */
+#define R_AARCH64_TLSLE_LDST64_TPREL_LO12 558 /* TP-rel. LD/ST off. 11:3. */
+#define R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC 559 /* Likewise; no check. */
+#define R_AARCH64_TLSDESC_LD_PREL19 560 /* PC-rel. load immediate 20:2. */
+#define R_AARCH64_TLSDESC_ADR_PREL21 561 /* PC-rel. ADR immediate 20:0. */
+#define R_AARCH64_TLSDESC_ADR_PAGE21 562 /* Page-rel. ADRP imm. 32:12. */
+#define R_AARCH64_TLSDESC_LD64_LO12 563 /* Direct LD off. from 11:3. */
+#define R_AARCH64_TLSDESC_ADD_LO12 564 /* Direct ADD imm. from 11:0. */
+#define R_AARCH64_TLSDESC_OFF_G1 565 /* GOT-rel. MOV{N,Z} imm. 31:16. */
+#define R_AARCH64_TLSDESC_OFF_G0_NC 566 /* GOT-rel. MOVK imm. 15:0; no ck. */
+#define R_AARCH64_TLSDESC_LDR 567 /* Relax LDR. */
+#define R_AARCH64_TLSDESC_ADD 568 /* Relax ADD. */
+#define R_AARCH64_TLSDESC_CALL 569 /* Relax BLR. */
+#define R_AARCH64_TLSLE_LDST128_TPREL_LO12 570 /* TP-rel. LD/ST off. 11:4. */
+#define R_AARCH64_TLSLE_LDST128_TPREL_LO12_NC 571 /* Likewise; no check. */
+#define R_AARCH64_TLSLD_LDST128_DTPREL_LO12 572 /* DTP-rel. LD/ST imm. 11:4. */
+#define R_AARCH64_TLSLD_LDST128_DTPREL_LO12_NC 573 /* Likewise; no check. */
+#define R_AARCH64_COPY 1024 /* Copy symbol at runtime. */
+#define R_AARCH64_GLOB_DAT 1025 /* Create GOT entry. */
+#define R_AARCH64_JUMP_SLOT 1026 /* Create PLT entry. */
+#define R_AARCH64_RELATIVE 1027 /* Adjust by program base. */
+#define R_AARCH64_TLS_DTPMOD 1028 /* Module number, 64 bit. */
+#define R_AARCH64_TLS_DTPREL 1029 /* Module-relative offset, 64 bit. */
+#define R_AARCH64_TLS_TPREL 1030 /* TP-relative offset, 64 bit. */
+#define R_AARCH64_TLSDESC 1031 /* TLS Descriptor. */
+#define R_AARCH64_IRELATIVE 1032 /* STT_GNU_IFUNC relocation. */
+
/* ARM relocs. */
#define R_ARM_NONE 0 /* No reloc */
diff --git a/ldso/include/dl-syscall.h b/ldso/include/dl-syscall.h
index 5528ba6a0..3baddd323 100644
--- a/ldso/include/dl-syscall.h
+++ b/ldso/include/dl-syscall.h
@@ -96,6 +96,16 @@ static __always_inline int _dl_stat(const char *file_name,
{
return _dl_fstatat64(AT_FDCWD, file_name, buf, 0);
}
+#elif defined __NR_newfstatat && !defined __NR_stat
+# define __NR__dl_newfstatat __NR_newfstatat
+static __always_inline _syscall4(int, _dl_newfstatat, int, fd, const char *,
+ fn, struct stat *, stat, int, flags)
+
+static __always_inline int _dl_stat(const char *file_name,
+ struct stat *buf)
+{
+ return _dl_newfstatat(AT_FDCWD, file_name, buf, 0);
+}
#elif defined __NR_stat
# define __NR__dl_stat __NR_stat
static __always_inline _syscall2(int, _dl_stat, const char *, file_name,
diff --git a/ldso/ldso/aarch64/dl-startup.h b/ldso/ldso/aarch64/dl-startup.h
new file mode 100644
index 000000000..1fac5ec35
--- /dev/null
+++ b/ldso/ldso/aarch64/dl-startup.h
@@ -0,0 +1,98 @@
+/*
+ * Architecture specific code used by dl-startup.c
+ * Copyright (C) 2016 Waldemar Brodkorb <wbx@uclibc-ng.org>
+ * Ported from GNU libc
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+/* Copyright (C) 1995-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 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 <features.h>
+
+__asm__("\
+.text \n\
+.globl _start \n\
+.type _start, %function \n\
+.globl _dl_start_user \n\
+.type _dl_start_user, %function \n\
+_start: \n\
+ mov x0, sp \n\
+ bl _dl_start \n\
+ // returns user entry point in x0 \n\
+ mov x21, x0 \n\
+_dl_start_user: \n\
+ // get the original arg count \n\
+ ldr x1, [sp] \n\
+ // get the argv address \n\
+ add x2, sp, #(1<<3) \n\
+ // get _dl_skip_args to see if we were \n\
+ // invoked as an executable \n\
+ adrp x4, _dl_skip_args \n\
+ ldr w4, [x4, #:lo12:_dl_skip_args] \n\
+ // do we need to adjust argc/argv \n\
+ cmp w4, 0 \n\
+ beq .L_done_stack_adjust \n\
+ // subtract _dl_skip_args from original arg count \n\
+ sub x1, x1, x4 \n\
+ // store adjusted argc back to stack \n\
+ str x1, [sp] \n\
+ // find the first unskipped argument \n\
+ mov x3, x2 \n\
+ add x4, x2, x4, lsl #3 \n\
+ // shuffle envp down \n\
+1: ldr x5, [x4], #(1<<3) \n\
+ str x5, [x3], #(1<<3) \n\
+ cmp x5, #0 \n\
+ bne 1b \n\
+ // shuffle auxv down \n\
+1: ldp x0, x5, [x4, #(2<<3)]! \n\
+ stp x0, x5, [x3], #(2<<3) \n\
+ cmp x0, #0 \n\
+ bne 1b \n\
+.L_done_stack_adjust: \n\
+ // compute envp \n\
+ add x3, x2, x1, lsl #3 \n\
+ add x3, x3, #(1<<3) \n\
+ // load the finalizer function \n\
+ adrp x0, _dl_fini \n\
+ add x0, x0, #:lo12:_dl_fini \n\
+ // jump to the user_s entry point \n\
+ br x21 \n\
+");
+
+/* Get a pointer to the argv array. On many platforms this can be just
+ * the address of the first argument, on other platforms we need to
+ * do something a little more subtle here. */
+#define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long*)ARGS)+1)
+
+/* Handle relocation of the symbols in the dynamic loader. */
+static __always_inline
+void PERFORM_BOOTSTRAP_RELOC(ELF_RELOC *rpnt, ElfW(Addr) *reloc_addr,
+ ElfW(Addr) symbol_addr, ElfW(Addr) load_addr, ElfW(Addr) *sym)
+{
+ switch (ELF_R_TYPE(rpnt->r_info)) {
+ case R_AARCH64_NONE:
+ break;
+ case R_AARCH64_ABS64:
+ case R_AARCH64_GLOB_DAT:
+ case R_AARCH64_JUMP_SLOT:
+ *reloc_addr = symbol_addr + rpnt->r_addend;
+ break;
+ default:
+ _dl_exit(1);
+ }
+}
diff --git a/ldso/ldso/aarch64/dl-syscalls.h b/ldso/ldso/aarch64/dl-syscalls.h
new file mode 100644
index 000000000..f40c4fd31
--- /dev/null
+++ b/ldso/ldso/aarch64/dl-syscalls.h
@@ -0,0 +1 @@
+/* stub for arch-specific syscall issues */
diff --git a/ldso/ldso/aarch64/dl-sysdep.h b/ldso/ldso/aarch64/dl-sysdep.h
new file mode 100644
index 000000000..4e8cdd906
--- /dev/null
+++ b/ldso/ldso/aarch64/dl-sysdep.h
@@ -0,0 +1,107 @@
+/*
+ * Various assembly language/system dependent hacks that are required
+ * so that we can minimize the amount of platform specific code.
+ * Copyright (C) 2000-2004 by Erik Andersen <andersen@codepoet.org>
+ * Copyright (C) 2017 by Waldemar Brodkorb <wbx@uclibc-ng.org>
+ * Ported from GNU C Library
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+/* Copyright (C) 1995-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 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/>. */
+
+/* Define this if the system uses RELOCA. */
+#define ELF_USES_RELOCA
+
+#include <elf.h>
+#include <link.h>
+
+/* Initialization sequence for the GOT. */
+#define INIT_GOT(GOT_BASE,MODULE) \
+{ \
+ GOT_BASE[2] = (unsigned long) _dl_linux_resolve; \
+ GOT_BASE[1] = (unsigned long) MODULE; \
+}
+
+/* Here we define the magic numbers that this dynamic loader should accept */
+#define MAGIC1 EM_AARCH64
+#undef MAGIC2
+
+/* Used for error messages */
+#define ELF_TARGET "aarch64"
+
+struct elf_resolve;
+unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry);
+
+#define elf_machine_type_class(type) \
+ ((((type) == R_AARCH64_JUMP_SLOT \
+ || (type) == R_AARCH64_TLS_DTPMOD \
+ || (type) == R_AARCH64_TLS_DTPREL \
+ || (type) == R_AARCH64_TLS_TPREL \
+ || (type) == R_AARCH64_TLSDESC) * ELF_RTYPE_CLASS_PLT) \
+ | (((type) == R_AARCH64_COPY) * ELF_RTYPE_CLASS_COPY))
+
+/* Return the link-time address of _DYNAMIC. Conveniently, this is the
+ first element of the GOT. */
+extern const ElfW(Addr) _GLOBAL_OFFSET_TABLE_[] attribute_hidden;
+static __always_inline ElfW(Addr) __attribute__ ((unused))
+elf_machine_dynamic (void)
+{
+ return _GLOBAL_OFFSET_TABLE_[0];
+}
+
+/* Return the run-time load address of the shared object. */
+
+static __always_inline ElfW(Addr) __attribute__ ((unused))
+elf_machine_load_address (void)
+{
+ /* To figure out the load address we use the definition that for any symbol:
+ dynamic_addr(symbol) = static_addr(symbol) + load_addr
+
+ The choice of symbol is arbitrary. The static address we obtain
+ by constructing a non GOT reference to the symbol, the dynamic
+ address of the symbol we compute using adrp/add to compute the
+ symbol's address relative to the PC.
+ This depends on 32/16bit relocations being resolved at link time
+ and that the static address fits in the 32/16 bits. */
+
+ ElfW(Addr) static_addr;
+ ElfW(Addr) dynamic_addr;
+
+ __asm__(" \n"
+" adrp %1, _dl_start; \n"
+" add %1, %1, #:lo12:_dl_start \n"
+" ldr %w0, 1f \n"
+" b 2f \n"
+"1: \n"
+" .word _dl_start \n"
+"2: \n"
+ : "=r" (static_addr), "=r" (dynamic_addr));
+ return dynamic_addr - static_addr;
+}
+
+static __always_inline void
+elf_machine_relative(Elf64_Addr load_off, const Elf64_Addr rel_addr,
+ Elf64_Word relative_count)
+{
+ Elf64_Rela *rpnt = (Elf64_Rela*)rel_addr;
+ --rpnt;
+ do {
+ Elf64_Addr *const reloc_addr = (Elf64_Addr*)(load_off + (++rpnt)->r_offset);
+
+ *reloc_addr = load_off + rpnt->r_addend;
+ } while (--relative_count);
+}
diff --git a/ldso/ldso/aarch64/dl-tlsdesc.S b/ldso/ldso/aarch64/dl-tlsdesc.S
new file mode 100644
index 000000000..4520da69b
--- /dev/null
+++ b/ldso/ldso/aarch64/dl-tlsdesc.S
@@ -0,0 +1,207 @@
+/*
+ * Copyright (C) 2017 Waldemar Brodkorb <wbx@uclibc-ng.org>
+ * Ported from GNU C Library
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+/* Thread-local storage handling in the ELF dynamic linker.
+ AArch64 version.
+ Copyright (C) 2011-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 <sysdep.h>
+
+#if defined __UCLIBC_HAS_TLS__
+
+#include <tls.h>
+#include "tlsdesc.h"
+
+#define PTR_REG(n) x##n
+#define PTR_LOG_SIZE 3
+#define PTR_SIZE (1<<PTR_LOG_SIZE)
+
+#define NSAVEDQREGPAIRS 16
+#define SAVE_Q_REGISTERS \
+ stp q0, q1, [sp, #-32*NSAVEDQREGPAIRS]!; \
+ cfi_adjust_cfa_offset (32*NSAVEDQREGPAIRS); \
+ stp q2, q3, [sp, #32*1]; \
+ stp q4, q5, [sp, #32*2]; \
+ stp q6, q7, [sp, #32*3]; \
+ stp q8, q9, [sp, #32*4]; \
+ stp q10, q11, [sp, #32*5]; \
+ stp q12, q13, [sp, #32*6]; \
+ stp q14, q15, [sp, #32*7]; \
+ stp q16, q17, [sp, #32*8]; \
+ stp q18, q19, [sp, #32*9]; \
+ stp q20, q21, [sp, #32*10]; \
+ stp q22, q23, [sp, #32*11]; \
+ stp q24, q25, [sp, #32*12]; \
+ stp q26, q27, [sp, #32*13]; \
+ stp q28, q29, [sp, #32*14]; \
+ stp q30, q31, [sp, #32*15];
+
+#define RESTORE_Q_REGISTERS \
+ ldp q2, q3, [sp, #32*1]; \
+ ldp q4, q5, [sp, #32*2]; \
+ ldp q6, q7, [sp, #32*3]; \
+ ldp q8, q9, [sp, #32*4]; \
+ ldp q10, q11, [sp, #32*5]; \
+ ldp q12, q13, [sp, #32*6]; \
+ ldp q14, q15, [sp, #32*7]; \
+ ldp q16, q17, [sp, #32*8]; \
+ ldp q18, q19, [sp, #32*9]; \
+ ldp q20, q21, [sp, #32*10]; \
+ ldp q22, q23, [sp, #32*11]; \
+ ldp q24, q25, [sp, #32*12]; \
+ ldp q26, q27, [sp, #32*13]; \
+ ldp q28, q29, [sp, #32*14]; \
+ ldp q30, q31, [sp, #32*15]; \
+ ldp q0, q1, [sp], #32*NSAVEDQREGPAIRS; \
+ cfi_adjust_cfa_offset (-32*NSAVEDQREGPAIRS);
+
+ .text
+
+ /* Compute the thread pointer offset for symbols in the static
+ TLS block. The offset is the same for all threads.
+ Prototype:
+ _dl_tlsdesc_return (tlsdesc *) ;
+ */
+ .hidden _dl_tlsdesc_return
+ .global _dl_tlsdesc_return
+ .type _dl_tlsdesc_return,%function
+ .align 2
+_dl_tlsdesc_return:
+ ldr x0,[x0,#8]
+ ret
+ .size _dl_tlsdesc_return, .-_dl_tlsdesc_return
+
+#ifdef SHARED
+ /* Handler for dynamic TLS symbols.
+ Prototype:
+ _dl_tlsdesc_dynamic (tlsdesc *) ;
+
+ The second word of the descriptor points to a
+ tlsdesc_dynamic_arg structure.
+
+ Returns the offset between the thread pointer and the
+ object referenced by the argument.
+
+ ptrdiff_t
+ __attribute__ ((__regparm__ (1)))
+ _dl_tlsdesc_dynamic (struct tlsdesc *tdp)
+ {
+ struct tlsdesc_dynamic_arg *td = tdp->arg;
+ dtv_t *dtv = *(dtv_t **)((char *)__thread_pointer + TCBHEAD_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
+ - __thread_pointer;
+
+ return ___tls_get_addr (&td->tlsinfo) - __thread_pointer;
+ }
+ */
+
+ .hidden _dl_tlsdesc_dynamic
+ .global _dl_tlsdesc_dynamic
+ .type _dl_tlsdesc_dynamic,%function
+ cfi_startproc
+ .align 2
+_dl_tlsdesc_dynamic:
+# define NSAVEXREGPAIRS 2
+ stp x29, x30, [sp,#-(32+16*NSAVEXREGPAIRS)]!
+ cfi_adjust_cfa_offset (32+16*NSAVEXREGPAIRS)
+ mov x29, sp
+
+ /* Save just enough registers to support fast path, if we fall
+ into slow path we will save additional registers. */
+
+ stp x1, x2, [sp, #32+16*0]
+ stp x3, x4, [sp, #32+16*1]
+
+ mrs x4, tpidr_el0
+ /* The ldar here happens after the load from [x0] at the call site
+ (that is generated by the compiler as part of the TLS access ABI),
+ so it reads the same value (this function is the final value of
+ td->entry) and thus it synchronizes with the release store to
+ td->entry in _dl_tlsdesc_resolve_rela_fixup ensuring that the load
+ from [x0,#PTR_SIZE] here happens after the initialization of td->arg. */
+ ldar PTR_REG (zr), [x0]
+ ldr PTR_REG (1), [x0,#TLSDESC_ARG]
+ ldr PTR_REG (0), [x4,#TCBHEAD_DTV]
+ ldr PTR_REG (3), [x1,#TLSDESC_GEN_COUNT]
+ ldr PTR_REG (2), [x0,#DTV_COUNTER]
+ cmp PTR_REG (3), PTR_REG (2)
+ b.hi 2f
+ ldr PTR_REG (2), [x1,#TLSDESC_MODID]
+ add PTR_REG (0), PTR_REG (0), PTR_REG (2), lsl #(PTR_LOG_SIZE + 1)
+ ldr PTR_REG (0), [x0] /* Load val member of DTV entry. */
+ cmp x0, #TLS_DTV_UNALLOCATED
+ b.eq 2f
+ ldr PTR_REG (1), [x1,#TLSDESC_MODOFF]
+ add PTR_REG (0), PTR_REG (0), PTR_REG (1)
+ sub PTR_REG (0), PTR_REG (0), PTR_REG (4)
+1:
+ ldp x1, x2, [sp, #32+16*0]
+ ldp x3, x4, [sp, #32+16*1]
+
+ ldp x29, x30, [sp], #(32+16*NSAVEXREGPAIRS)
+ cfi_adjust_cfa_offset (-32-16*NSAVEXREGPAIRS)
+# undef NSAVEXREGPAIRS
+ ret
+2:
+ /* This is the slow path. We need to call __tls_get_addr() which
+ means we need to save and restore all the register that the
+ callee will trash. */
+
+ /* Save the remaining registers that we must treat as caller save. */
+# define NSAVEXREGPAIRS 7
+ stp x5, x6, [sp, #-16*NSAVEXREGPAIRS]!
+ cfi_adjust_cfa_offset (16*NSAVEXREGPAIRS)
+ stp x7, x8, [sp, #16*1]
+ stp x9, x10, [sp, #16*2]
+ stp x11, x12, [sp, #16*3]
+ stp x13, x14, [sp, #16*4]
+ stp x15, x16, [sp, #16*5]
+ stp x17, x18, [sp, #16*6]
+
+ SAVE_Q_REGISTERS
+
+ mov x0, x1
+ bl __tls_get_addr
+
+ mrs x1, tpidr_el0
+ sub PTR_REG (0), PTR_REG (0), PTR_REG (1)
+
+ RESTORE_Q_REGISTERS
+
+ ldp x7, x8, [sp, #16*1]
+ ldp x9, x10, [sp, #16*2]
+ ldp x11, x12, [sp, #16*3]
+ ldp x13, x14, [sp, #16*4]
+ ldp x15, x16, [sp, #16*5]
+ ldp x17, x18, [sp, #16*6]
+ ldp x5, x6, [sp], #16*NSAVEXREGPAIRS
+ cfi_adjust_cfa_offset (-16*NSAVEXREGPAIRS)
+ b 1b
+ cfi_endproc
+ .size _dl_tlsdesc_dynamic, .-_dl_tlsdesc_dynamic
+# undef NSAVEXREGPAIRS
+
+#endif // SHARED
+#endif // __UCLIBC_HAS_TLS__
diff --git a/ldso/ldso/aarch64/elfinterp.c b/ldso/ldso/aarch64/elfinterp.c
new file mode 100644
index 000000000..879484e16
--- /dev/null
+++ b/ldso/ldso/aarch64/elfinterp.c
@@ -0,0 +1,306 @@
+/* AARCH64 ELF shared library loader suppport
+ *
+ * Copyright (C) 2001-2004 Erik Andersen
+ * Copyright (C) 2016-2017 Waldemar Brodkorb <wbx@uclibc-ng.org>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. The name of the above contributors may not be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* Program to load an ELF binary on a linux system, and run it.
+ References to symbols in sharable libraries can be resolved by either
+ an ELF sharable library or a linux style of shared library. */
+
+#include "ldso.h"
+
+#if defined(USE_TLS) && USE_TLS
+#include "dl-tls.h"
+#include "tlsdeschtab.h"
+#endif
+
+extern int _dl_linux_resolve(void);
+
+unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
+{
+ ELF_RELOC *this_reloc;
+ char *strtab;
+ ElfW(Sym) *symtab;
+ int symtab_index;
+ char *rel_addr;
+ char *new_addr;
+ char **got_addr;
+ ElfW(Addr) instr_addr;
+ char *symname;
+
+ rel_addr = (char *)tpnt->dynamic_info[DT_JMPREL];
+ this_reloc = (ELF_RELOC *)(rel_addr + reloc_entry);
+ symtab_index = ELF_R_SYM(this_reloc->r_info);
+
+ symtab = (ElfW(Sym) *)tpnt->dynamic_info[DT_SYMTAB];
+ strtab = (char *)tpnt->dynamic_info[DT_STRTAB];
+ symname = strtab + symtab[symtab_index].st_name;
+
+ /* Address of jump instruction to fix up */
+ instr_addr = (this_reloc->r_offset + tpnt->loadaddr);
+ got_addr = (char **)instr_addr;
+
+ /* Get the address of the GOT entry */
+ new_addr = _dl_find_hash(symname, &_dl_loaded_modules->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
+ if (unlikely(!new_addr)) {
+ _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", _dl_progname, symname);
+ _dl_exit(1);
+ }
+#if defined (__SUPPORT_LD_DEBUG__)
+ if (_dl_debug_bindings) {
+ _dl_dprintf(_dl_debug_file, "\nresolve function: %s", symname);
+ if (_dl_debug_detail) _dl_dprintf(_dl_debug_file,
+ "\tpatched %x ==> %x @ %x", *got_addr, new_addr, got_addr);
+ }
+ if (!_dl_debug_nofixups) {
+ *got_addr = new_addr;
+ }
+#else
+ *got_addr = new_addr;
+#endif
+ return (unsigned long)new_addr;
+}
+
+static int
+_dl_parse(struct elf_resolve *tpnt, struct r_scope_elem *scope,
+ unsigned long rel_addr, unsigned long rel_size,
+ int (*reloc_fnc) (struct elf_resolve *tpnt, struct r_scope_elem *scope,
+ ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab))
+{
+ unsigned int i;
+ char *strtab;
+ ElfW(Sym) *symtab;
+ ELF_RELOC *rpnt;
+ int symtab_index;
+
+ /* Parse the relocation information */
+ rpnt = (ELF_RELOC *)rel_addr;
+ rel_size = rel_size / sizeof(ELF_RELOC);
+
+ symtab = (ElfW(Sym) *)tpnt->dynamic_info[DT_SYMTAB];
+ strtab = (char *)tpnt->dynamic_info[DT_STRTAB];
+
+ for (i = 0; i < rel_size; i++, rpnt++) {
+ int res;
+
+ symtab_index = ELF_R_SYM(rpnt->r_info);
+
+ debug_sym(symtab, strtab, symtab_index);
+ debug_reloc(symtab, strtab, rpnt);
+
+ res = reloc_fnc(tpnt, scope, rpnt, symtab, strtab);
+
+ if (res==0)
+ continue;
+
+ _dl_dprintf(2, "\n%s: ", _dl_progname);
+
+ if (symtab_index)
+ _dl_dprintf(2, "symbol '%s': ",
+ strtab + symtab[symtab_index].st_name);
+
+ if (unlikely(res < 0)) {
+ int reloc_type = ELF_R_TYPE(rpnt->r_info);
+ _dl_dprintf(2, "can't handle reloc type %x\n", reloc_type);
+ _dl_exit(-res);
+ } else if (unlikely(res > 0)) {
+ _dl_dprintf(2, "can't resolve symbol\n");
+ return res;
+ }
+ }
+
+ return 0;
+}
+
+static int
+_dl_do_reloc (struct elf_resolve *tpnt, struct r_scope_elem *scope,
+ ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab)
+{
+ int reloc_type;
+ int symtab_index;
+ char *symname;
+#if defined USE_TLS && USE_TLS
+ struct elf_resolve *tls_tpnt = NULL;
+#endif
+ struct symbol_ref sym_ref;
+ ElfW(Addr) *reloc_addr;
+ ElfW(Addr) symbol_addr;
+#if defined (__SUPPORT_LD_DEBUG__)
+ ElfW(Addr) old_val;
+#endif
+
+ reloc_addr = (ElfW(Addr)*)(tpnt->loadaddr + (unsigned long)rpnt->r_offset);
+ reloc_type = ELF_R_TYPE(rpnt->r_info);
+ symtab_index = ELF_R_SYM(rpnt->r_info);
+ sym_ref.sym = &symtab[symtab_index];
+ sym_ref.tpnt = NULL;
+ symbol_addr = 0;
+ symname = strtab + sym_ref.sym->st_name;
+
+ if (symtab_index) {
+ symbol_addr = (ElfW(Addr))_dl_find_hash(symname, scope, tpnt,
+ elf_machine_type_class(reloc_type), &sym_ref);
+
+ /*
+ * We want to allow undefined references to weak symbols - this might
+ * have been intentional. We should not be linking local symbols
+ * here, so all bases should be covered.
+ */
+ if (unlikely (!symbol_addr &&
+ (ELF_ST_TYPE(symtab[symtab_index].st_info) != STT_TLS) &&
+ (ELF_ST_BIND(symtab[symtab_index].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
+ } else {
+ /*
+ * Relocs against STN_UNDEF are usually treated as using a
+ * symbol value of zero, and using the module containing the
+ * reloc itself.
+ */
+ symbol_addr = sym_ref.sym->st_value;
+#if defined USE_TLS && USE_TLS
+ tls_tpnt = tpnt;
+#endif
+ }
+
+#if defined (__SUPPORT_LD_DEBUG__)
+ old_val = *reloc_addr;
+#endif
+
+ switch (reloc_type) {
+ case R_AARCH64_NONE:
+ break;
+ case R_AARCH64_ABS64: /* REL_SYMBOLIC */
+ case R_AARCH64_GLOB_DAT: /* REL_GOT */
+ case R_AARCH64_JUMP_SLOT: /* REL_PLT */
+ *reloc_addr = symbol_addr + rpnt->r_addend;
+ break;
+ case R_AARCH64_RELATIVE:
+ *reloc_addr += tpnt->loadaddr + rpnt->r_addend;
+ break;
+ case R_AARCH64_COPY:
+ _dl_memcpy((void *) reloc_addr,
+ (void *) symbol_addr, sym_ref.sym->st_size);
+ break;
+#if defined USE_TLS && USE_TLS
+ case R_AARCH64_TLS_TPREL:
+ CHECK_STATIC_TLS ((struct link_map *) tls_tpnt);
+ *reloc_addr = (symbol_addr + tls_tpnt->l_tls_offset);
+ break;
+ case R_AARCH64_TLSDESC:
+ {
+ struct tlsdesc volatile *td =
+ (struct tlsdesc volatile *)reloc_addr;
+#ifndef SHARED
+ CHECK_STATIC_TLS((struct link_map *) tls_tpnt);
+#else
+ if (!TRY_STATIC_TLS ((struct link_map *) tls_tpnt))
+ {
+ td->arg = _dl_make_tlsdesc_dynamic((struct link_map *) tls_tpnt, symbol_addr);
+ td->entry = _dl_tlsdesc_dynamic;
+ }
+ else
+#endif
+ {
+ td->arg = symbol_addr + tls_tpnt->l_tls_offset;
+ td->entry = _dl_tlsdesc_return;
+ }
+ }
+ break;
+#endif
+ default:
+ return -1; /*call _dl_exit(1) */
+ }
+
+#if defined (__SUPPORT_LD_DEBUG__)
+ if (_dl_debug_reloc && _dl_debug_detail) {
+ _dl_dprintf(_dl_debug_file, "\tpatched: %x ==> %x @ %x\n",
+ old_val, *reloc_addr, reloc_addr);
+ }
+#endif
+
+ return 0;
+}
+
+static int
+_dl_do_lazy_reloc (struct elf_resolve *tpnt, struct r_scope_elem *scope,
+ ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab)
+{
+ int reloc_type;
+ ElfW(Addr) *reloc_addr;
+#if defined (__SUPPORT_LD_DEBUG__)
+ ElfW(Addr) old_val;
+#endif
+
+ (void)scope;
+ (void)strtab;
+
+ reloc_addr = (ElfW(Addr)*)(tpnt->loadaddr + rpnt->r_offset);
+ reloc_type = ELF_R_TYPE(rpnt->r_info);
+
+#if defined (__SUPPORT_LD_DEBUG__)
+ old_val = *reloc_addr;
+#endif
+
+ switch (reloc_type) {
+ case R_AARCH64_NONE:
+ break;
+ case R_AARCH64_JUMP_SLOT:
+ *reloc_addr += tpnt->loadaddr;
+ break;
+ default:
+ return -1; /*call _dl_exit(1) */
+ }
+
+#if defined (__SUPPORT_LD_DEBUG__)
+ if (_dl_debug_reloc && _dl_debug_detail) {
+ _dl_dprintf(_dl_debug_file, "\tpatched_lazy: %x ==> %x @ %x\n",
+ old_val, *reloc_addr, reloc_addr);
+ }
+#endif
+
+ return 0;
+}
+
+void _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt,
+ unsigned long rel_addr, unsigned long rel_size)
+{
+ (void)_dl_parse(rpnt->dyn, NULL, rel_addr, rel_size, _dl_do_lazy_reloc);
+}
+
+int _dl_parse_relocation_information(struct dyn_elf *rpnt,
+ struct r_scope_elem *scope, unsigned long rel_addr, unsigned long rel_size)
+{
+ return _dl_parse(rpnt->dyn, scope, rel_addr, rel_size, _dl_do_reloc);
+}
diff --git a/ldso/ldso/aarch64/resolve.S b/ldso/ldso/aarch64/resolve.S
new file mode 100644
index 000000000..3b907c46c
--- /dev/null
+++ b/ldso/ldso/aarch64/resolve.S
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2016 by Waldemar Brodkorb <wbx@uclibc-ng.org>
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ * ported from GNU libc
+ */
+
+/* Copyright (C) 2005-2016 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/>. */
+
+#include <features.h>
+
+#define PTR_REG(n) x##n
+#define PTR_LOG_SIZE 3
+#define PTR_SIZE (1<<PTR_LOG_SIZE)
+
+#define ip0 x16
+#define ip0l PTR_REG (16)
+#define ip1 x17
+#define lr x30
+
+/* RELA relocatons are 3 pointers */
+#define RELA_SIZE (PTR_SIZE * 3)
+
+ .text
+ .globl _dl_linux_resolve
+ .type _dl_linux_resolve, %function
+ .align 2
+
+_dl_linux_resolve:
+ /* AArch64 we get called with:
+ ip0 &PLTGOT[2]
+ ip1 temp(dl resolver entry point)
+ [sp, #8] lr
+ [sp, #0] &PLTGOT[n]
+ */
+
+ /* Save arguments. */
+ stp x8, x9, [sp, #-(80+8*16)]!
+ stp x6, x7, [sp, #16]
+ stp x4, x5, [sp, #32]
+ stp x2, x3, [sp, #48]
+ stp x0, x1, [sp, #64]
+ stp q0, q1, [sp, #(80+0*16)]
+ stp q2, q3, [sp, #(80+2*16)]
+ stp q4, q5, [sp, #(80+4*16)]
+ stp q6, q7, [sp, #(80+6*16)]
+
+ /* Get pointer to linker struct. */
+ ldr PTR_REG (0), [ip0, #-PTR_SIZE]
+
+ /* Prepare to call _dl_linux_resolver(). */
+ ldr x1, [sp, 80+8*16] /* Recover &PLTGOT[n] */
+
+ sub x1, x1, ip0
+ add x1, x1, x1, lsl #1
+ lsl x1, x1, #3
+ sub x1, x1, #(RELA_SIZE<<3)
+ lsr x1, x1, #3
+
+ /* Call resolver routine. */
+ bl _dl_linux_resolver
+
+ /* Save the return. */
+ mov ip0, x0
+
+ /* Get arguments and return address back. */
+ ldp q0, q1, [sp, #(80+0*16)]
+ ldp q2, q3, [sp, #(80+2*16)]
+ ldp q4, q5, [sp, #(80+4*16)]
+ ldp q6, q7, [sp, #(80+6*16)]
+ ldp x0, x1, [sp, #64]
+ ldp x2, x3, [sp, #48]
+ ldp x4, x5, [sp, #32]
+ ldp x6, x7, [sp, #16]
+ ldp x8, x9, [sp], #(80+8*16)
+
+ ldp ip1, lr, [sp], #16
+
+ /* Jump to the newly found address. */
+ br ip0
+
+.size _dl_linux_resolve, .-_dl_linux_resolve
diff --git a/libc/string/aarch64/Makefile b/libc/string/aarch64/Makefile
new file mode 100644
index 000000000..0a95346fd
--- /dev/null
+++ b/libc/string/aarch64/Makefile
@@ -0,0 +1,13 @@
+# Makefile for uClibc
+#
+# Copyright (C) 2000-2005 Erik Andersen <andersen@uclibc.org>
+#
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+#
+
+top_srcdir:=../../../
+top_builddir:=../../../
+all: objs
+include $(top_builddir)Rules.mak
+include ../Makefile.in
+include $(top_srcdir)Makerules
diff --git a/libc/string/aarch64/memcpy.S b/libc/string/aarch64/memcpy.S
new file mode 100644
index 000000000..87b2552a2
--- /dev/null
+++ b/libc/string/aarch64/memcpy.S
@@ -0,0 +1,230 @@
+/* Copyright (C) 2012-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 <sysdep.h>
+
+/* Assumptions:
+ *
+ * ARMv8-a, AArch64, unaligned accesses.
+ *
+ */
+
+#define dstin x0
+#define src x1
+#define count x2
+#define dst x3
+#define srcend x4
+#define dstend x5
+#define A_l x6
+#define A_lw w6
+#define A_h x7
+#define A_hw w7
+#define B_l x8
+#define B_lw w8
+#define B_h x9
+#define C_l x10
+#define C_h x11
+#define D_l x12
+#define D_h x13
+#define E_l src
+#define E_h count
+#define F_l srcend
+#define F_h dst
+#define G_l count
+#define G_h dst
+#define tmp1 x14
+
+ENTRY (memcpy)
+
+ prfm PLDL1KEEP, [src]
+ add srcend, src, count
+ add dstend, dstin, count
+ cmp count, 16
+ b.ls L(copy16)
+ cmp count, 96
+ b.hi L(copy_long)
+
+ /* Medium copies: 17..96 bytes. */
+ sub tmp1, count, 1
+ ldp A_l, A_h, [src]
+ tbnz tmp1, 6, L(copy96)
+ ldp D_l, D_h, [srcend, -16]
+ tbz tmp1, 5, 1f
+ ldp B_l, B_h, [src, 16]
+ ldp C_l, C_h, [srcend, -32]
+ stp B_l, B_h, [dstin, 16]
+ stp C_l, C_h, [dstend, -32]
+1:
+ stp A_l, A_h, [dstin]
+ stp D_l, D_h, [dstend, -16]
+ ret
+
+ .p2align 4
+ /* Small copies: 0..16 bytes. */
+L(copy16):
+ cmp count, 8
+ b.lo 1f
+ ldr A_l, [src]
+ ldr A_h, [srcend, -8]
+ str A_l, [dstin]
+ str A_h, [dstend, -8]
+ ret
+ .p2align 4
+1:
+ tbz count, 2, 1f
+ ldr A_lw, [src]
+ ldr A_hw, [srcend, -4]
+ str A_lw, [dstin]
+ str A_hw, [dstend, -4]
+ ret
+
+ /* Copy 0..3 bytes. Use a branchless sequence that copies the same
+ byte 3 times if count==1, or the 2nd byte twice if count==2. */
+1:
+ cbz count, 2f
+ lsr tmp1, count, 1
+ ldrb A_lw, [src]
+ ldrb A_hw, [srcend, -1]
+ ldrb B_lw, [src, tmp1]
+ strb A_lw, [dstin]
+ strb B_lw, [dstin, tmp1]
+ strb A_hw, [dstend, -1]
+2: ret
+
+ .p2align 4
+ /* Copy 64..96 bytes. Copy 64 bytes from the start and
+ 32 bytes from the end. */
+L(copy96):
+ ldp B_l, B_h, [src, 16]
+ ldp C_l, C_h, [src, 32]
+ ldp D_l, D_h, [src, 48]
+ ldp E_l, E_h, [srcend, -32]
+ ldp F_l, F_h, [srcend, -16]
+ stp A_l, A_h, [dstin]
+ stp B_l, B_h, [dstin, 16]
+ stp C_l, C_h, [dstin, 32]
+ stp D_l, D_h, [dstin, 48]
+ stp E_l, E_h, [dstend, -32]
+ stp F_l, F_h, [dstend, -16]
+ ret
+
+ /* Align DST to 16 byte alignment so that we don't cross cache line
+ boundaries on both loads and stores. There are at least 96 bytes
+ to copy, so copy 16 bytes unaligned and then align. The loop
+ copies 64 bytes per iteration and prefetches one iteration ahead. */
+
+ .p2align 4
+L(copy_long):
+ and tmp1, dstin, 15
+ bic dst, dstin, 15
+ ldp D_l, D_h, [src]
+ sub src, src, tmp1
+ add count, count, tmp1 /* Count is now 16 too large. */
+ ldp A_l, A_h, [src, 16]
+ stp D_l, D_h, [dstin]
+ ldp B_l, B_h, [src, 32]
+ ldp C_l, C_h, [src, 48]
+ ldp D_l, D_h, [src, 64]!
+ subs count, count, 128 + 16 /* Test and readjust count. */
+ b.ls 2f
+1:
+ stp A_l, A_h, [dst, 16]
+ ldp A_l, A_h, [src, 16]
+ stp B_l, B_h, [dst, 32]
+ ldp B_l, B_h, [src, 32]
+ stp C_l, C_h, [dst, 48]
+ ldp C_l, C_h, [src, 48]
+ stp D_l, D_h, [dst, 64]!
+ ldp D_l, D_h, [src, 64]!
+ subs count, count, 64
+ b.hi 1b
+
+ /* Write the last full set of 64 bytes. The remainder is at most 64
+ bytes, so it is safe to always copy 64 bytes from the end even if
+ there is just 1 byte left. */
+2:
+ ldp E_l, E_h, [srcend, -64]
+ stp A_l, A_h, [dst, 16]
+ ldp A_l, A_h, [srcend, -48]
+ stp B_l, B_h, [dst, 32]
+ ldp B_l, B_h, [srcend, -32]
+ stp C_l, C_h, [dst, 48]
+ ldp C_l, C_h, [srcend, -16]
+ stp D_l, D_h, [dst, 64]
+ stp E_l, E_h, [dstend, -64]
+ stp A_l, A_h, [dstend, -48]
+ stp B_l, B_h, [dstend, -32]
+ stp C_l, C_h, [dstend, -16]
+ ret
+
+ .p2align 4
+L(move_long):
+ cbz tmp1, 3f
+
+ add srcend, src, count
+ add dstend, dstin, count
+
+ /* Align dstend to 16 byte alignment so that we don't cross cache line
+ boundaries on both loads and stores. There are at least 96 bytes
+ to copy, so copy 16 bytes unaligned and then align. The loop
+ copies 64 bytes per iteration and prefetches one iteration ahead. */
+
+ and tmp1, dstend, 15
+ ldp D_l, D_h, [srcend, -16]
+ sub srcend, srcend, tmp1
+ sub count, count, tmp1
+ ldp A_l, A_h, [srcend, -16]
+ stp D_l, D_h, [dstend, -16]
+ ldp B_l, B_h, [srcend, -32]
+ ldp C_l, C_h, [srcend, -48]
+ ldp D_l, D_h, [srcend, -64]!
+ sub dstend, dstend, tmp1
+ subs count, count, 128
+ b.ls 2f
+
+ nop
+1:
+ stp A_l, A_h, [dstend, -16]
+ ldp A_l, A_h, [srcend, -16]
+ stp B_l, B_h, [dstend, -32]
+ ldp B_l, B_h, [srcend, -32]
+ stp C_l, C_h, [dstend, -48]
+ ldp C_l, C_h, [srcend, -48]
+ stp D_l, D_h, [dstend, -64]!
+ ldp D_l, D_h, [srcend, -64]!
+ subs count, count, 64
+ b.hi 1b
+
+ /* Write the last full set of 64 bytes. The remainder is at most 64
+ bytes, so it is safe to always copy 64 bytes from the start even if
+ there is just 1 byte left. */
+2:
+ ldp G_l, G_h, [src, 48]
+ stp A_l, A_h, [dstend, -16]
+ ldp A_l, A_h, [src, 32]
+ stp B_l, B_h, [dstend, -32]
+ ldp B_l, B_h, [src, 16]
+ stp C_l, C_h, [dstend, -48]
+ ldp C_l, C_h, [src]
+ stp D_l, D_h, [dstend, -64]
+ stp G_l, G_h, [dstin, 48]
+ stp A_l, A_h, [dstin, 32]
+ stp B_l, B_h, [dstin, 16]
+ stp C_l, C_h, [dstin]
+3: ret
+
+END (memcpy)
+libc_hidden_def (memcpy)
diff --git a/libc/string/aarch64/memset.S b/libc/string/aarch64/memset.S
new file mode 100644
index 000000000..d6686bedc
--- /dev/null
+++ b/libc/string/aarch64/memset.S
@@ -0,0 +1,189 @@
+/* Copyright (C) 2012-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 <sysdep.h>
+
+/* Assumptions:
+ *
+ * ARMv8-a, AArch64, unaligned accesses
+ *
+ */
+
+#define dstin x0
+#define val x1
+#define valw w1
+#define count x2
+#define dst x3
+#define dstend x4
+#define tmp1 x5
+#define tmp1w w5
+#define tmp2 x6
+#define tmp2w w6
+#define zva_len x7
+#define zva_lenw w7
+
+ENTRY_ALIGN (memset, 6)
+
+ dup v0.16B, valw
+ add dstend, dstin, count
+
+ cmp count, 96
+ b.hi L(set_long)
+ cmp count, 16
+ b.hs L(set_medium)
+ mov val, v0.D[0]
+
+ /* Set 0..15 bytes. */
+ tbz count, 3, 1f
+ str val, [dstin]
+ str val, [dstend, -8]
+ ret
+ nop
+1: tbz count, 2, 2f
+ str valw, [dstin]
+ str valw, [dstend, -4]
+ ret
+2: cbz count, 3f
+ strb valw, [dstin]
+ tbz count, 1, 3f
+ strh valw, [dstend, -2]
+3: ret
+
+ /* Set 17..96 bytes. */
+L(set_medium):
+ str q0, [dstin]
+ tbnz count, 6, L(set96)
+ str q0, [dstend, -16]
+ tbz count, 5, 1f
+ str q0, [dstin, 16]
+ str q0, [dstend, -32]
+1: ret
+
+ .p2align 4
+ /* Set 64..96 bytes. Write 64 bytes from the start and
+ 32 bytes from the end. */
+L(set96):
+ str q0, [dstin, 16]
+ stp q0, q0, [dstin, 32]
+ stp q0, q0, [dstend, -32]
+ ret
+
+ .p2align 3
+ nop
+L(set_long):
+ and valw, valw, 255
+ bic dst, dstin, 15
+ str q0, [dstin]
+ cmp count, 256
+ ccmp valw, 0, 0, cs
+ b.eq L(try_zva)
+L(no_zva):
+ sub count, dstend, dst /* Count is 16 too large. */
+ add dst, dst, 16
+ sub count, count, 64 + 16 /* Adjust count and bias for loop. */
+1: stp q0, q0, [dst], 64
+ stp q0, q0, [dst, -32]
+L(tail64):
+ subs count, count, 64
+ b.hi 1b
+2: stp q0, q0, [dstend, -64]
+ stp q0, q0, [dstend, -32]
+ ret
+
+ .p2align 3
+L(try_zva):
+ mrs tmp1, dczid_el0
+ tbnz tmp1w, 4, L(no_zva)
+ and tmp1w, tmp1w, 15
+ cmp tmp1w, 4 /* ZVA size is 64 bytes. */
+ b.ne L(zva_128)
+
+ /* Write the first and last 64 byte aligned block using stp rather
+ than using DC ZVA. This is faster on some cores.
+ */
+L(zva_64):
+ str q0, [dst, 16]
+ stp q0, q0, [dst, 32]
+ bic dst, dst, 63
+ stp q0, q0, [dst, 64]
+ stp q0, q0, [dst, 96]
+ sub count, dstend, dst /* Count is now 128 too large. */
+ sub count, count, 128+64+64 /* Adjust count and bias for loop. */
+ add dst, dst, 128
+ nop
+1: dc zva, dst
+ add dst, dst, 64
+ subs count, count, 64
+ b.hi 1b
+ stp q0, q0, [dst, 0]
+ stp q0, q0, [dst, 32]
+ stp q0, q0, [dstend, -64]
+ stp q0, q0, [dstend, -32]
+ ret
+
+ .p2align 3
+L(zva_128):
+ cmp tmp1w, 5 /* ZVA size is 128 bytes. */
+ b.ne L(zva_other)
+
+ str q0, [dst, 16]
+ stp q0, q0, [dst, 32]
+ stp q0, q0, [dst, 64]
+ stp q0, q0, [dst, 96]
+ bic dst, dst, 127
+ sub count, dstend, dst /* Count is now 128 too large. */
+ sub count, count, 128+128 /* Adjust count and bias for loop. */
+ add dst, dst, 128
+1: dc zva, dst
+ add dst, dst, 128
+ subs count, count, 128
+ b.hi 1b
+ stp q0, q0, [dstend, -128]
+ stp q0, q0, [dstend, -96]
+ stp q0, q0, [dstend, -64]
+ stp q0, q0, [dstend, -32]
+ ret
+
+L(zva_other):
+ mov tmp2w, 4
+ lsl zva_lenw, tmp2w, tmp1w
+ add tmp1, zva_len, 64 /* Max alignment bytes written. */
+ cmp count, tmp1
+ blo L(no_zva)
+
+ sub tmp2, zva_len, 1
+ add tmp1, dst, zva_len
+ add dst, dst, 16
+ subs count, tmp1, dst /* Actual alignment bytes to write. */
+ bic tmp1, tmp1, tmp2 /* Aligned dc zva start address. */
+ beq 2f
+1: stp q0, q0, [dst], 64
+ stp q0, q0, [dst, -32]
+ subs count, count, 64
+ b.hi 1b
+2: mov dst, tmp1
+ sub count, dstend, tmp1 /* Remaining bytes to write. */
+ subs count, count, zva_len
+ b.lo 4f
+3: dc zva, dst
+ add dst, dst, zva_len
+ subs count, count, zva_len
+ b.hs 3b
+4: add count, count, zva_len
+ b L(tail64)
+
+END (memset)
+libc_hidden_def (memset)
diff --git a/libc/sysdeps/linux/aarch64/Makefile b/libc/sysdeps/linux/aarch64/Makefile
new file mode 100644
index 000000000..86a32a613
--- /dev/null
+++ b/libc/sysdeps/linux/aarch64/Makefile
@@ -0,0 +1,9 @@
+# Makefile for uClibc-ng
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+
+top_srcdir=../../../../
+top_builddir=../../../../
+all: objs
+include $(top_builddir)Rules.mak
+include Makefile.arch
+include $(top_srcdir)Makerules
diff --git a/libc/sysdeps/linux/aarch64/Makefile.arch b/libc/sysdeps/linux/aarch64/Makefile.arch
new file mode 100644
index 000000000..b38f760a8
--- /dev/null
+++ b/libc/sysdeps/linux/aarch64/Makefile.arch
@@ -0,0 +1,5 @@
+# Makefile for uClibc-ng
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+
+CSRC-y := __syscall_error.c
+SSRC-y := clone.S setjmp.S syscall.S __longjmp.S bsd-setjmp.S bsd-_setjmp.S vfork.S
diff --git a/libc/sysdeps/linux/aarch64/__longjmp.S b/libc/sysdeps/linux/aarch64/__longjmp.S
new file mode 100644
index 000000000..e4d11b165
--- /dev/null
+++ b/libc/sysdeps/linux/aarch64/__longjmp.S
@@ -0,0 +1,107 @@
+/* Copyright (C) 1997-2016 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/>. */
+
+#include <sysdep.h>
+#include <jmpbuf-offsets.h>
+
+/* __longjmp(jmpbuf, val) */
+
+ENTRY (__longjmp)
+ cfi_def_cfa(x0, 0)
+ cfi_offset(x19, JB_X19<<3)
+ cfi_offset(x20, JB_X20<<3)
+ cfi_offset(x21, JB_X21<<3)
+ cfi_offset(x22, JB_X22<<3)
+ cfi_offset(x23, JB_X23<<3)
+ cfi_offset(x24, JB_X24<<3)
+ cfi_offset(x25, JB_X25<<3)
+ cfi_offset(x26, JB_X26<<3)
+ cfi_offset(x27, JB_X27<<3)
+ cfi_offset(x28, JB_X28<<3)
+ cfi_offset(x29, JB_X29<<3)
+ cfi_offset(x30, JB_LR<<3)
+
+ cfi_offset( d8, JB_D8<<3)
+ cfi_offset( d9, JB_D9<<3)
+ cfi_offset(d10, JB_D10<<3)
+ cfi_offset(d11, JB_D11<<3)
+ cfi_offset(d12, JB_D12<<3)
+ cfi_offset(d13, JB_D13<<3)
+ cfi_offset(d14, JB_D14<<3)
+ cfi_offset(d15, JB_D15<<3)
+
+ ldp x19, x20, [x0, #JB_X19<<3]
+ ldp x21, x22, [x0, #JB_X21<<3]
+ ldp x23, x24, [x0, #JB_X23<<3]
+ ldp x25, x26, [x0, #JB_X25<<3]
+ ldp x27, x28, [x0, #JB_X27<<3]
+ ldp x29, x30, [x0, #JB_X29<<3]
+
+ /* longjmp probe takes 3 arguments, address of jump buffer as
+ first argument (8@x0), return value as second argument (-4@x1),
+ and target address (8@x30), respectively. */
+ //LIBC_PROBE (longjmp, 3, 8@x0, -4@x1, 8@x30)
+ ldp d8, d9, [x0, #JB_D8<<3]
+ ldp d10, d11, [x0, #JB_D10<<3]
+ ldp d12, d13, [x0, #JB_D12<<3]
+ ldp d14, d15, [x0, #JB_D14<<3]
+
+ /* Originally this was implemented with a series of
+ .cfi_restore() directives.
+
+ The theory was that cfi_restore should revert to previous
+ frame value is the same as the current value. In practice
+ this doesn't work, even after cfi_restore() gdb continues
+ to try to recover a previous frame value offset from x0,
+ which gets stuffed after a few more instructions. The
+ cfi_same_value() mechanism appears to work fine. */
+
+ cfi_same_value(x19)
+ cfi_same_value(x20)
+ cfi_same_value(x21)
+ cfi_same_value(x22)
+ cfi_same_value(x23)
+ cfi_same_value(x24)
+ cfi_same_value(x25)
+ cfi_same_value(x26)
+ cfi_same_value(x27)
+ cfi_same_value(x28)
+ cfi_same_value(x29)
+ cfi_same_value(x30)
+ cfi_same_value(d8)
+ cfi_same_value(d9)
+ cfi_same_value(d10)
+ cfi_same_value(d11)
+ cfi_same_value(d12)
+ cfi_same_value(d13)
+ cfi_same_value(d14)
+ cfi_same_value(d15)
+ ldr x5, [x0, #JB_SP<<3]
+ mov sp, x5
+
+ /* longjmp_target probe takes 3 arguments, address of jump buffer
+ as first argument (8@x0), return value as second argument (-4@x1),
+ and target address (8@x30), respectively. */
+ //LIBC_PROBE (longjmp_target, 3, 8@x0, -4@x1, 8@x30)
+ cmp x1, #0
+ mov x0, #1
+ csel x0, x1, x0, ne
+ /* Use br instead of ret because ret is guaranteed to mispredict */
+ br x30
+END (__longjmp)
+libc_hidden_def(__longjmp)
diff --git a/libc/sysdeps/linux/aarch64/__syscall_error.c b/libc/sysdeps/linux/aarch64/__syscall_error.c
new file mode 100644
index 000000000..2b642e816
--- /dev/null
+++ b/libc/sysdeps/linux/aarch64/__syscall_error.c
@@ -0,0 +1,18 @@
+/* Wrapper for setting errno.
+ *
+ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#include <errno.h>
+#include <features.h>
+
+/* This routine is jumped to by all the syscall handlers, to stash
+ * an error number into errno. */
+int __syscall_error(int err_no) attribute_hidden;
+int __syscall_error(int err_no)
+{
+ __set_errno(-err_no);
+ return -1;
+}
diff --git a/libc/sysdeps/linux/aarch64/bits/atomic.h b/libc/sysdeps/linux/aarch64/bits/atomic.h
new file mode 100644
index 000000000..66e2f57d6
--- /dev/null
+++ b/libc/sysdeps/linux/aarch64/bits/atomic.h
@@ -0,0 +1,172 @@
+/* Copyright (C) 2003-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 _AARCH64_ATOMIC_MACHINE_H
+#define _AARCH64_ATOMIC_MACHINE_H 1
+
+#define typeof __typeof__
+
+#include <stdint.h>
+#include <sysdep.h>
+
+typedef int8_t atomic8_t;
+typedef int16_t atomic16_t;
+typedef int32_t atomic32_t;
+typedef int64_t atomic64_t;
+
+typedef uint8_t uatomic8_t;
+typedef uint16_t uatomic16_t;
+typedef uint32_t uatomic32_t;
+typedef uint64_t uatomic64_t;
+
+typedef intptr_t atomicptr_t;
+typedef uintptr_t uatomicptr_t;
+typedef intmax_t atomic_max_t;
+typedef uintmax_t uatomic_max_t;
+
+#define __HAVE_64B_ATOMICS 1
+#define USE_ATOMIC_COMPILER_BUILTINS 1
+
+/* Compare and exchange.
+ For all "bool" routines, we return FALSE if exchange succesful. */
+
+# define __arch_compare_and_exchange_bool_8_int(mem, newval, oldval, model) \
+ ({ \
+ typeof (*mem) __oldval = (oldval); \
+ !__atomic_compare_exchange_n (mem, (void *) &__oldval, newval, 0, \
+ model, __ATOMIC_RELAXED); \
+ })
+
+# define __arch_compare_and_exchange_bool_16_int(mem, newval, oldval, model) \
+ ({ \
+ typeof (*mem) __oldval = (oldval); \
+ !__atomic_compare_exchange_n (mem, (void *) &__oldval, newval, 0, \
+ model, __ATOMIC_RELAXED); \
+ })
+
+# define __arch_compare_and_exchange_bool_32_int(mem, newval, oldval, model) \
+ ({ \
+ typeof (*mem) __oldval = (oldval); \
+ !__atomic_compare_exchange_n (mem, (void *) &__oldval, newval, 0, \
+ model, __ATOMIC_RELAXED); \
+ })
+
+# define __arch_compare_and_exchange_bool_64_int(mem, newval, oldval, model) \
+ ({ \
+ typeof (*mem) __oldval = (oldval); \
+ !__atomic_compare_exchange_n (mem, (void *) &__oldval, newval, 0, \
+ model, __ATOMIC_RELAXED); \
+ })
+
+# define __arch_compare_and_exchange_val_8_int(mem, newval, oldval, model) \
+ ({ \
+ typeof (*mem) __oldval = (oldval); \
+ __atomic_compare_exchange_n (mem, (void *) &__oldval, newval, 0, \
+ model, __ATOMIC_RELAXED); \
+ __oldval; \
+ })
+
+# define __arch_compare_and_exchange_val_16_int(mem, newval, oldval, model) \
+ ({ \
+ typeof (*mem) __oldval = (oldval); \
+ __atomic_compare_exchange_n (mem, (void *) &__oldval, newval, 0, \
+ model, __ATOMIC_RELAXED); \
+ __oldval; \
+ })
+
+# define __arch_compare_and_exchange_val_32_int(mem, newval, oldval, model) \
+ ({ \
+ typeof (*mem) __oldval = (oldval); \
+ __atomic_compare_exchange_n (mem, (void *) &__oldval, newval, 0, \
+ model, __ATOMIC_RELAXED); \
+ __oldval; \
+ })
+
+# define __arch_compare_and_exchange_val_64_int(mem, newval, oldval, model) \
+ ({ \
+ typeof (*mem) __oldval = (oldval); \
+ __atomic_compare_exchange_n (mem, (void *) &__oldval, newval, 0, \
+ model, __ATOMIC_RELAXED); \
+ __oldval; \
+ })
+
+
+/* Compare and exchange with "acquire" semantics, ie barrier after. */
+
+# define atomic_compare_and_exchange_bool_acq(mem, new, old) \
+ __atomic_bool_bysize (__arch_compare_and_exchange_bool, int, \
+ mem, new, old, __ATOMIC_ACQUIRE)
+
+# define atomic_compare_and_exchange_val_acq(mem, new, old) \
+ __atomic_val_bysize (__arch_compare_and_exchange_val, int, \
+ mem, new, old, __ATOMIC_ACQUIRE)
+
+/* Compare and exchange with "release" semantics, ie barrier before. */
+
+# define atomic_compare_and_exchange_val_rel(mem, new, old) \
+ __atomic_val_bysize (__arch_compare_and_exchange_val, int, \
+ mem, new, old, __ATOMIC_RELEASE)
+
+
+/* Atomic exchange (without compare). */
+
+# define __arch_exchange_8_int(mem, newval, model) \
+ __atomic_exchange_n (mem, newval, model)
+
+# define __arch_exchange_16_int(mem, newval, model) \
+ __atomic_exchange_n (mem, newval, model)
+
+# define __arch_exchange_32_int(mem, newval, model) \
+ __atomic_exchange_n (mem, newval, model)
+
+# define __arch_exchange_64_int(mem, newval, model) \
+ __atomic_exchange_n (mem, newval, model)
+
+# define atomic_exchange_acq(mem, value) \
+ __atomic_val_bysize (__arch_exchange, int, mem, value, __ATOMIC_ACQUIRE)
+
+# define atomic_exchange_rel(mem, value) \
+ __atomic_val_bysize (__arch_exchange, int, mem, value, __ATOMIC_RELEASE)
+
+
+/* Atomically add value and return the previous (unincremented) value. */
+
+# define __arch_exchange_and_add_8_int(mem, value, model) \
+ __atomic_fetch_add (mem, value, model)
+
+# define __arch_exchange_and_add_16_int(mem, value, model) \
+ __atomic_fetch_add (mem, value, model)
+
+# define __arch_exchange_and_add_32_int(mem, value, model) \
+ __atomic_fetch_add (mem, value, model)
+
+# define __arch_exchange_and_add_64_int(mem, value, model) \
+ __atomic_fetch_add (mem, value, model)
+
+# define atomic_exchange_and_add_acq(mem, value) \
+ __atomic_val_bysize (__arch_exchange_and_add, int, mem, value, \
+ __ATOMIC_ACQUIRE)
+
+# define atomic_exchange_and_add_rel(mem, value) \
+ __atomic_val_bysize (__arch_exchange_and_add, int, mem, value, \
+ __ATOMIC_RELEASE)
+
+/* Barrier macro. */
+#define atomic_full_barrier() __sync_synchronize()
+
+#endif
diff --git a/libc/sysdeps/linux/aarch64/bits/endian.h b/libc/sysdeps/linux/aarch64/bits/endian.h
new file mode 100644
index 000000000..a32ebc0d8
--- /dev/null
+++ b/libc/sysdeps/linux/aarch64/bits/endian.h
@@ -0,0 +1,30 @@
+/* Copyright (C) 1997-2016 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 _ENDIAN_H
+# error "Never use <bits/endian.h> directly; include <endian.h> instead."
+#endif
+
+/* AArch64 can be either big or little endian. */
+#ifdef __AARCH64EB__
+# define __BYTE_ORDER __BIG_ENDIAN
+#else
+# define __BYTE_ORDER __LITTLE_ENDIAN
+#endif
+
+#define __FLOAT_WORD_ORDER __BYTE_ORDER
diff --git a/libc/sysdeps/linux/aarch64/bits/fcntl.h b/libc/sysdeps/linux/aarch64/bits/fcntl.h
new file mode 100644
index 000000000..d05798f31
--- /dev/null
+++ b/libc/sysdeps/linux/aarch64/bits/fcntl.h
@@ -0,0 +1,329 @@
+/* O_*, F_*, FD_* bit values for the AArch64 Linux ABI.
+ Copyright (C) 2011-2016 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 _FCNTL_H
+# error "Never use <bits/fcntl.h> directly; include <fcntl.h> instead."
+#endif
+
+#include <sys/types.h>
+#ifdef __USE_GNU
+# include <bits/uio.h>
+#endif
+
+/* open/fcntl. */
+#define O_ACCMODE 0003
+#define O_RDONLY 00
+#define O_WRONLY 01
+#define O_RDWR 02
+#define O_CREAT 0100 /* Not fcntl. */
+#define O_EXCL 0200 /* Not fcntl. */
+#define O_NOCTTY 0400 /* Not fcntl. */
+#define O_TRUNC 01000 /* Not fcntl. */
+#define O_APPEND 02000
+#define O_NONBLOCK 04000
+#define O_NDELAY O_NONBLOCK
+#define O_SYNC 04010000
+#define O_FSYNC O_SYNC
+#define O_ASYNC 020000
+
+#ifdef __USE_GNU
+# define O_DIRECTORY 040000
+# define O_NOFOLLOW 0100000
+# define O_DIRECT 0200000
+# define O_NOATIME 01000000
+# define O_CLOEXEC 02000000
+# define O_PATH 010000000
+#endif
+
+/* For now Linux has synchronisity options for data and read operations.
+ We define the symbols here but let them do the same as O_SYNC since
+ this is a superset. */
+#if defined __USE_POSIX199309 || defined __USE_UNIX98
+# define O_DSYNC O_SYNC /* Synchronize data. */
+# define O_RSYNC O_SYNC /* Synchronize read operations. */
+#endif
+
+#ifdef __USE_LARGEFILE64
+# define O_LARGEFILE 0
+#endif
+
+/* Values for the second argument to `fcntl'. */
+#define F_DUPFD 0 /* Duplicate file descriptor. */
+#define F_GETFD 1 /* Get file descriptor flags. */
+#define F_SETFD 2 /* Set file descriptor flags. */
+#define F_GETFL 3 /* Get file status flags. */
+#define F_SETFL 4 /* Set file status flags. */
+#ifndef __USE_FILE_OFFSET64
+# define F_GETLK 5 /* Get record locking info. */
+# define F_SETLK 6 /* Set record locking info (non-blocking). */
+# define F_SETLKW 7 /* Set record locking info (blocking). */
+#else
+# define F_GETLK F_GETLK64 /* Get record locking info. */
+# define F_SETLK F_SETLK64 /* Set record locking info (non-blocking).*/
+# define F_SETLKW F_SETLKW64 /* Set record locking info (blocking). */
+#endif
+#define F_GETLK64 5 /* Get record locking info. */
+#define F_SETLK64 6 /* Set record locking info (non-blocking). */
+#define F_SETLKW64 7 /* Set record locking info (blocking). */
+
+#if defined __USE_BSD || defined __USE_UNIX98
+# define F_SETOWN 8 /* Get owner of socket (receiver of SIGIO). */
+# define F_GETOWN 9 /* Set owner of socket (receiver of SIGIO). */
+#endif
+
+#ifdef __USE_GNU
+# define F_SETSIG 10 /* Set number of signal to be sent. */
+# define F_GETSIG 11 /* Get number of signal to be sent. */
+# define F_SETOWN_EX 15 /* Get owner (thread receiving SIGIO). */
+# define F_GETOWN_EX 16 /* Set owner (thread receiving SIGIO). */
+#endif
+
+
+#ifdef __USE_GNU
+# define F_SETLEASE 1024 /* Set a lease. */
+# define F_GETLEASE 1025 /* Enquire what lease is active. */
+# define F_NOTIFY 1026 /* Request notifications on a directory. */
+# define F_SETPIPE_SZ 1031 /* Set pipe page size array. */
+# define F_GETPIPE_SZ 1032 /* Set pipe page size array. */
+#endif
+#ifdef __USE_XOPEN2K8
+# define F_DUPFD_CLOEXEC 1030 /* Duplicate file descriptor with
+ close-on-exit set. */
+#endif
+
+/* For F_[GET|SET]FD. */
+#define FD_CLOEXEC 1 /* Actually anything with low bit set goes */
+
+/* For posix fcntl() and `l_type' field of a `struct flock' for lockf(). */
+# define F_RDLCK 0 /* Read lock. */
+# define F_WRLCK 1 /* Write lock. */
+# define F_UNLCK 2 /* Remove lock. */
+
+/* For old implementation of BSD flock. */
+#define F_EXLCK 4 /* or 3 */
+#define F_SHLCK 8 /* or 4 */
+
+#ifdef __USE_BSD
+/* Operations for BSD flock, also used by the kernel implementation. */
+# define LOCK_SH 1 /* Shared lock. */
+# define LOCK_EX 2 /* Exclusive lock. */
+# define LOCK_NB 4 /* Or'd with one of the above to prevent
+ blocking. */
+# define LOCK_UN 8 /* Remove lock. */
+#endif
+
+#ifdef __USE_GNU
+# define LOCK_MAND 32 /* This is a mandatory flock: */
+# define LOCK_READ 64 /* ... which allows concurrent read operations. */
+# define LOCK_WRITE 128 /* ... which allows concurrent write operations. */
+# define LOCK_RW 192 /* ... Which allows concurrent read & write operations. */
+#endif
+
+#ifdef __USE_GNU
+/* Types of directory notifications that may be requested with F_NOTIFY. */
+# define DN_ACCESS 0x00000001 /* File accessed. */
+# define DN_MODIFY 0x00000002 /* File modified. */
+# define DN_CREATE 0x00000004 /* File created. */
+# define DN_DELETE 0x00000008 /* File removed. */
+# define DN_RENAME 0x00000010 /* File renamed. */
+# define DN_ATTRIB 0x00000020 /* File changed attributes. */
+# define DN_MULTISHOT 0x80000000 /* Don't remove notifier. */
+#endif
+
+struct flock
+ {
+ short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */
+ short int l_whence; /* Where `l_start' is relative to (like `lseek'). */
+ __off_t l_start; /* Offset where the lock begins. */
+ __off_t l_len; /* Size of the locked area; zero means until EOF. */
+ __pid_t l_pid; /* Process holding the lock. */
+ };
+
+#ifdef __USE_LARGEFILE64
+struct flock64
+ {
+ short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */
+ short int l_whence; /* Where `l_start' is relative to (like `lseek'). */
+ __off64_t l_start; /* Offset where the lock begins. */
+ __off64_t l_len; /* Size of the locked area; zero means until EOF. */
+ __pid_t l_pid; /* Process holding the lock. */
+ };
+#endif
+
+
+#ifdef __USE_GNU
+/* Owner types. */
+enum __pid_type
+ {
+ F_OWNER_TID = 0, /* Kernel thread. */
+ F_OWNER_PID, /* Process. */
+ F_OWNER_PGRP, /* Process group. */
+ F_OWNER_GID = F_OWNER_PGRP /* Alternative, obsolete name. */
+ };
+
+/* Structure to use with F_GETOWN_EX and F_SETOWN_EX. */
+struct f_owner_ex
+ {
+ enum __pid_type type; /* Owner type of ID. */
+ __pid_t pid; /* ID of owner. */
+ };
+#endif
+
+/* Define some more compatibility macros to be backward compatible with
+ BSD systems which did not managed to hide these kernel macros. */
+#ifdef __USE_BSD
+# define FAPPEND O_APPEND
+# define FFSYNC O_FSYNC
+# define FASYNC O_ASYNC
+# define FNONBLOCK O_NONBLOCK
+# define FNDELAY O_NDELAY
+#endif /* Use BSD. */
+
+/* Advise to `posix_fadvise'. */
+#ifdef __USE_XOPEN2K
+# define POSIX_FADV_NORMAL 0 /* No further special treatment. */
+# define POSIX_FADV_RANDOM 1 /* Expect random page references. */
+# define POSIX_FADV_SEQUENTIAL 2 /* Expect sequential page references. */
+# define POSIX_FADV_WILLNEED 3 /* Will need these pages. */
+# define POSIX_FADV_DONTNEED 4 /* Don't need these pages. */
+# define POSIX_FADV_NOREUSE 5 /* Data will be accessed once. */
+#endif
+
+
+#if defined __USE_GNU && defined __UCLIBC_LINUX_SPECIFIC__
+/* Flags for SYNC_FILE_RANGE. */
+# define SYNC_FILE_RANGE_WAIT_BEFORE 1 /* Wait upon writeout of all pages
+ in the range before performing the
+ write. */
+# define SYNC_FILE_RANGE_WRITE 2 /* Initiate writeout of all those
+ dirty pages in the range which are
+ not presently under writeback. */
+# define SYNC_FILE_RANGE_WAIT_AFTER 4 /* Wait upon writeout of all pages in
+ the range after performing the
+ write. */
+
+/* Flags for SPLICE and VMSPLICE. */
+# define SPLICE_F_MOVE 1 /* Move pages instead of copying. */
+# define SPLICE_F_NONBLOCK 2 /* Don't block on the pipe splicing
+ (but we may still block on the fd
+ we splice from/to). */
+# define SPLICE_F_MORE 4 /* Expect more data. */
+# define SPLICE_F_GIFT 8 /* Pages passed in are a gift. */
+
+
+/* Flags for fallocate. */
+# define FALLOC_FL_KEEP_SIZE 1 /* Don't extend size of file
+ even if offset + len is
+ greater than file size. */
+# define FALLOC_FL_PUNCH_HOLE 2 /* Create a hole in the file. */
+# define FALLOC_FL_COLLAPSE_RANGE 8 /* Remove a range of a file
+ without leaving a
+ hole. */
+# define FALLOC_FL_ZERO_RANGE 16 /* Convert a range of a
+ file to zeros. */
+
+
+/* File handle structure. */
+struct file_handle
+{
+ unsigned int handle_bytes;
+ int handle_type;
+ /* File identifier. */
+ unsigned char f_handle[0];
+};
+
+/* Maximum handle size (for now). */
+# define MAX_HANDLE_SZ 128
+#endif
+
+__BEGIN_DECLS
+
+#if defined __USE_GNU && defined __UCLIBC_LINUX_SPECIFIC__
+
+/* Provide kernel hint to read ahead. */
+extern ssize_t readahead (int __fd, __off64_t __offset, size_t __count)
+ __THROW;
+
+
+/* Selective file content synch'ing.
+
+ This function is a possible cancellation point and therefore not
+ marked with __THROW. */
+extern int sync_file_range (int __fd, __off64_t __offset, __off64_t __count,
+ unsigned int __flags);
+
+
+/* Splice address range into a pipe.
+
+ This function is a possible cancellation point and therefore not
+ marked with __THROW. */
+extern ssize_t vmsplice (int __fdout, const struct iovec *__iov,
+ size_t __count, unsigned int __flags);
+
+/* Splice two files together.
+
+ This function is a possible cancellation point and therefore not
+ marked with __THROW. */
+extern ssize_t splice (int __fdin, __off64_t *__offin, int __fdout,
+ __off64_t *__offout, size_t __len,
+ unsigned int __flags);
+
+/* In-kernel implementation of tee for pipe buffers.
+
+ This function is a possible cancellation point and therefore not
+ marked with __THROW. */
+extern ssize_t tee (int __fdin, int __fdout, size_t __len,
+ unsigned int __flags);
+
+/* Reserve storage for the data of the file associated with FD.
+
+ This function is a possible cancellation point and therefore not
+ marked with __THROW. */
+# ifndef __USE_FILE_OFFSET64
+extern int fallocate (int __fd, int __mode, __off_t __offset, __off_t __len);
+# else
+# ifdef __REDIRECT
+extern int __REDIRECT (fallocate, (int __fd, int __mode, __off64_t __offset,
+ __off64_t __len),
+ fallocate64);
+# else
+# define fallocate fallocate64
+# endif
+# endif
+# ifdef __USE_LARGEFILE64
+extern int fallocate64 (int __fd, int __mode, __off64_t __offset,
+ __off64_t __len);
+# endif
+
+
+/* Map file name to file handle. */
+extern int name_to_handle_at (int __dfd, const char *__name,
+ struct file_handle *__handle, int *__mnt_id,
+ int __flags) __THROW;
+
+/* Open file using the file handle.
+
+ This function is a possible cancellation point and therefore not
+ marked with __THROW. */
+extern int open_by_handle_at (int __mountdirfd, struct file_handle *__handle,
+ int __flags);
+
+#endif /* use GNU */
+
+__END_DECLS
diff --git a/libc/sysdeps/linux/aarch64/bits/kernel_types.h b/libc/sysdeps/linux/aarch64/bits/kernel_types.h
new file mode 100644
index 000000000..832b17674
--- /dev/null
+++ b/libc/sysdeps/linux/aarch64/bits/kernel_types.h
@@ -0,0 +1,42 @@
+/* Note that we use the exact same include guard #define names
+ * as asm/posix_types.h. This will avoid gratuitous conflicts
+ * with the posix_types.h kernel header, and will ensure that
+ * our private content, and not the kernel header, will win.
+ * -Erik
+ */
+#ifndef __ASM_GENERIC_POSIX_TYPES_H
+#define __ASM_GENERIC_POSIX_TYPES_H
+
+typedef unsigned long __kernel_dev_t;
+typedef unsigned long __kernel_ino_t;
+typedef unsigned int __kernel_mode_t;
+typedef unsigned int __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 long __kernel_size_t;
+typedef long __kernel_ssize_t;
+typedef long __kernel_ptrdiff_t;
+typedef long __kernel_time_t;
+typedef long __kernel_suseconds_t;
+typedef long __kernel_clock_t;
+typedef int __kernel_daddr_t;
+typedef char * __kernel_caddr_t;
+typedef unsigned short __kernel_uid16_t;
+typedef unsigned short __kernel_gid16_t;
+typedef unsigned int __kernel_uid32_t;
+typedef unsigned int __kernel_gid32_t;
+typedef unsigned short __kernel_old_uid_t;
+typedef unsigned short __kernel_old_gid_t;
+typedef long long __kernel_loff_t;
+typedef unsigned int __kernel_old_dev_t;
+typedef long __kernel_long_t;
+typedef unsigned long __kernel_ulong_t;
+
+typedef struct {
+ int val[2];
+} __kernel_fsid_t;
+
+#endif /* __ASM_GENERIC_POSIX_TYPES_H */
diff --git a/libc/sysdeps/linux/aarch64/bits/setjmp.h b/libc/sysdeps/linux/aarch64/bits/setjmp.h
new file mode 100644
index 000000000..fff8616c6
--- /dev/null
+++ b/libc/sysdeps/linux/aarch64/bits/setjmp.h
@@ -0,0 +1,33 @@
+/* Copyright (C) 1997-2016 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 _BITS_SETJMP_H
+#define _BITS_SETJMP_H 1
+
+#if !defined _SETJMP_H && !defined _PTHREAD_H
+# error "Never include <bits/setjmp.h> directly; use <setjmp.h> instead."
+#endif
+
+#ifndef _ASM
+/* Jump buffer contains:
+ x19-x28, x29(fp), x30(lr), (x31)sp, d8-d15. Other registers are not
+ saved. */
+__extension__ typedef unsigned long long __jmp_buf [22];
+
+#endif
+#endif
diff --git a/libc/sysdeps/linux/aarch64/bits/stackinfo.h b/libc/sysdeps/linux/aarch64/bits/stackinfo.h
new file mode 100644
index 000000000..78f326203
--- /dev/null
+++ b/libc/sysdeps/linux/aarch64/bits/stackinfo.h
@@ -0,0 +1,33 @@
+/* Copyright (C) 2001-2016 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/>. */
+
+/* This file contains a bit of information about the stack allocation
+ of the processor. */
+
+#ifndef _STACKINFO_H
+#define _STACKINFO_H 1
+
+#include <elf.h>
+
+/* On AArch64 the stack grows down. */
+#define _STACK_GROWS_DOWN 1
+
+/* Default to a non-executable stack. */
+#define DEFAULT_STACK_PERMS (PF_R|PF_W)
+
+#endif /* stackinfo.h */
diff --git a/libc/sysdeps/linux/aarch64/bits/syscalls.h b/libc/sysdeps/linux/aarch64/bits/syscalls.h
new file mode 100644
index 000000000..3c0d840ea
--- /dev/null
+++ b/libc/sysdeps/linux/aarch64/bits/syscalls.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2016 by Waldemar Brodkorb <wbx@uclibc-ng.org>
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ * ported from GNU libc
+ */
+
+/* Copyright (C) 2005-2016 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 _BITS_SYSCALLS_H
+#define _BITS_SYSCALLS_H
+#ifndef _SYSCALL_H
+# error "Never use <bits/syscalls.h> directly; include <sys/syscall.h> instead."
+#endif
+
+#ifndef __ASSEMBLER__
+#include <errno.h>
+
+#define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \
+ ({ long _sys_result; \
+ { \
+ register long _x8 __asm__ ("x8"); \
+ LOAD_ARGS_##nr (args) \
+ _x8 = (name); \
+ \
+ __asm__ volatile ( \
+ "svc 0 // syscall " # name \
+ : "=r" (_x0) : "r"(_x8) ASM_ARGS_##nr \
+ : "memory"); \
+ \
+ _sys_result = _x0; \
+ } \
+ _sys_result; })
+
+/* Macros for setting up inline __asm__ input regs */
+# define ASM_ARGS_0
+# define ASM_ARGS_1 , "r" (_x0)
+# define ASM_ARGS_2 ASM_ARGS_1, "r" (_x1)
+# define ASM_ARGS_3 ASM_ARGS_2, "r" (_x2)
+# define ASM_ARGS_4 ASM_ARGS_3, "r" (_x3)
+# define ASM_ARGS_5 ASM_ARGS_4, "r" (_x4)
+# define ASM_ARGS_6 ASM_ARGS_5, "r" (_x5)
+# define ASM_ARGS_7 ASM_ARGS_6, "r" (_x6)
+
+/* Macros for converting sys-call wrapper args into sys call args */
+# define LOAD_ARGS_0() \
+ register long _x0 __asm__ ("x0");
+# define LOAD_ARGS_1(x0) \
+ long _x0tmp; \
+ LOAD_ARGS_0 () \
+ _x0tmp = (long) (x0); \
+ _x0 = _x0tmp;
+# define LOAD_ARGS_2(x0, x1) \
+ register long _x1 __asm__ ("x1"); \
+ long _x1tmp; \
+ LOAD_ARGS_1 (x0) \
+ _x1tmp = (long) (x1); \
+ _x1 = _x1tmp;
+# define LOAD_ARGS_3(x0, x1, x2) \
+ register long _x2 __asm__ ("x2"); \
+ long _x2tmp; \
+ LOAD_ARGS_2 (x0, x1) \
+ _x2tmp = (long) (x2); \
+ _x2 = _x2tmp;
+# define LOAD_ARGS_4(x0, x1, x2, x3) \
+ register long _x3 __asm__ ("x3"); \
+ long _x3tmp; \
+ LOAD_ARGS_3 (x0, x1, x2) \
+ _x3tmp = (long) (x3); \
+ _x3 = _x3tmp;
+# define LOAD_ARGS_5(x0, x1, x2, x3, x4) \
+ register long _x4 __asm__ ("x4"); \
+ long _x4tmp; \
+ LOAD_ARGS_4 (x0, x1, x2, x3) \
+ _x4tmp = (long) (x4); \
+ _x4 = _x4tmp;
+# define LOAD_ARGS_6(x0, x1, x2, x3, x4, x5) \
+ register long _x5 __asm__ ("x5"); \
+ long _x5tmp; \
+ LOAD_ARGS_5 (x0, x1, x2, x3, x4) \
+ _x5tmp = (long) (x5); \
+ _x5 = _x5tmp;
+# define LOAD_ARGS_7(x0, x1, x2, x3, x4, x5, x6)\
+ register long _x6 __asm__ ("x6"); \
+ long _x6tmp; \
+ LOAD_ARGS_6 (x0, x1, x2, x3, x4, x5) \
+ _x6tmp = (long) (x6); \
+ _x6 = _x6tmp;
+
+#endif /* ! __ASSEMBLER__ */
+#endif /* _BITS_SYSCALLS_H */
diff --git a/libc/sysdeps/linux/aarch64/bits/uClibc_arch_features.h b/libc/sysdeps/linux/aarch64/bits/uClibc_arch_features.h
new file mode 100644
index 000000000..7cae090ec
--- /dev/null
+++ b/libc/sysdeps/linux/aarch64/bits/uClibc_arch_features.h
@@ -0,0 +1,38 @@
+/*
+ * Track misc arch-specific features that aren't config options
+ */
+
+#ifndef _BITS_UCLIBC_ARCH_FEATURES_H
+#define _BITS_UCLIBC_ARCH_FEATURES_H
+
+/* instruction used when calling abort() to kill yourself */
+#define __UCLIBC_ABORT_INSTRUCTION__ "bl abort"
+
+/* can your target use syscall6() for mmap ? */
+#define __UCLIBC_MMAP_HAS_6_ARGS__
+
+/* does your target have a broken create_module() ? */
+#define __UCLIBC_BROKEN_CREATE_MODULE__
+
+/* does your target have to worry about older [gs]etrlimit() ? */
+#undef __UCLIBC_HANDLE_OLDER_RLIMIT__
+
+/* does your target have an asm .set ? */
+#define __UCLIBC_HAVE_ASM_SET_DIRECTIVE__
+
+/* define if target supports .weak */
+#define __UCLIBC_HAVE_ASM_WEAK_DIRECTIVE__
+
+/* define if target supports .weakext */
+#undef __UCLIBC_HAVE_ASM_WEAKEXT_DIRECTIVE__
+
+/* define if target supports CFI pseudo ops */
+#define __UCLIBC_HAVE_ASM_CFI_DIRECTIVES__
+
+/* define if target supports IEEE signed zero floats */
+#define __UCLIBC_HAVE_SIGNED_ZERO__
+
+/* only weird assemblers generally need this */
+#undef __UCLIBC_ASM_LINE_SEP__
+
+#endif /* _BITS_UCLIBC_ARCH_FEATURES_H */
diff --git a/libc/sysdeps/linux/aarch64/bits/uClibc_page.h b/libc/sysdeps/linux/aarch64/bits/uClibc_page.h
new file mode 100755
index 000000000..4f92abcf8
--- /dev/null
+++ b/libc/sysdeps/linux/aarch64/bits/uClibc_page.h
@@ -0,0 +1,25 @@
+/*
+ * Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in this tarball.
+ */
+
+#ifndef _UCLIBC_PAGE_H
+#define _UCLIBC_PAGE_H
+
+/*
+ * AARCH64 supports 4k, 16k, 64k pages (build time).
+ */
+
+#include <features.h>
+
+#if defined(__CONFIG_AARCH64_PAGE_SIZE_64K__)
+#define PAGE_SHIFT 16
+#elif defined(__CONFIG_AARCH64_PAGE_SIZE_16K__)
+#define PAGE_SHIFT 14
+#else
+#define PAGE_SHIFT 12
+#endif
+
+#define PAGE_SIZE (1UL << PAGE_SHIFT)
+#define PAGE_MASK (~(PAGE_SIZE-1))
+
+#endif /* _UCLIBC_PAGE_H */
diff --git a/libc/sysdeps/linux/aarch64/bits/wordsize.h b/libc/sysdeps/linux/aarch64/bits/wordsize.h
new file mode 100644
index 000000000..0944f9e26
--- /dev/null
+++ b/libc/sysdeps/linux/aarch64/bits/wordsize.h
@@ -0,0 +1,18 @@
+/* Copyright (C) 1999-2016 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/>. */
+
+#define __WORDSIZE 64
diff --git a/libc/sysdeps/linux/aarch64/bsd-_setjmp.S b/libc/sysdeps/linux/aarch64/bsd-_setjmp.S
new file mode 100644
index 000000000..4e6a2da56
--- /dev/null
+++ b/libc/sysdeps/linux/aarch64/bsd-_setjmp.S
@@ -0,0 +1 @@
+/* _setjmp is in setjmp.S */
diff --git a/libc/sysdeps/linux/aarch64/bsd-setjmp.S b/libc/sysdeps/linux/aarch64/bsd-setjmp.S
new file mode 100644
index 000000000..1da848d2f
--- /dev/null
+++ b/libc/sysdeps/linux/aarch64/bsd-setjmp.S
@@ -0,0 +1 @@
+/* setjmp is in setjmp.S */
diff --git a/libc/sysdeps/linux/aarch64/clone.S b/libc/sysdeps/linux/aarch64/clone.S
new file mode 100644
index 000000000..7437eec8d
--- /dev/null
+++ b/libc/sysdeps/linux/aarch64/clone.S
@@ -0,0 +1,85 @@
+/* Copyright (C) 1996-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/>. */
+
+/* clone() is even more special than fork() as it mucks with stacks
+ and invokes a function in the right context after its all over. */
+
+#include <sysdep.h>
+#define _ERRNO_H 1
+#include <bits/errno.h>
+
+#define CLONE_VM_BIT 8
+#define CLONE_VM (1 << CLONE_VM_BIT)
+
+#define CLONE_THREAD_BIT 16
+#define CLONE_THREAD (1 << CLONE_THREAD_BIT)
+
+/* int clone(int (*fn)(void *arg), x0
+ void *child_stack, x1
+ int flags, x2
+ void *arg, x3
+ pid_t *ptid, x4
+ struct user_desc *tls, x5
+ pid_t *ctid); x6
+ */
+ .text
+ENTRY(__clone)
+ /* Save args for the child. */
+ mov x10, x0
+ mov x11, x2
+ mov x12, x3
+
+ /* Sanity check args. */
+ mov x0, #-EINVAL
+ cbz x10, .Lsyscall_error
+ cbz x1, .Lsyscall_error
+
+ /* Do the system call. */
+ /* X0:flags, x1:newsp, x2:parenttidptr, x3:newtls, x4:childtid. */
+ mov x0, x2 /* flags */
+ /* New sp is already in x1. */
+ mov x2, x4 /* ptid */
+ mov x3, x5 /* tls */
+ mov x4, x6 /* ctid */
+ mov x8, #SYS_ify(clone)
+ svc 0x0
+
+ cmp x0, #0
+ beq thread_start
+ blt .Lsyscall_error
+ RET
+PSEUDO_END (__clone)
+
+ .align 4
+ .type thread_start, %function
+thread_start:
+ cfi_startproc
+ cfi_undefined (x30)
+ mov x29, 0
+
+ /* Pick the function arg and execute. */
+ mov x0, x12
+ blr x10
+
+ /* We are done, pass the return value through x0. */
+ b HIDDEN_JUMPTARGET(_exit)
+ cfi_endproc
+ .size thread_start, .-thread_start
+
+libc_hidden_def (__clone)
+weak_alias (__clone, clone)
diff --git a/libc/sysdeps/linux/aarch64/crt1.S b/libc/sysdeps/linux/aarch64/crt1.S
new file mode 100644
index 000000000..09d0327ac
--- /dev/null
+++ b/libc/sysdeps/linux/aarch64/crt1.S
@@ -0,0 +1,89 @@
+/* Copyright (C) 1995-2016 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/>. */
+
+/* This is the canonical entry point, usually the first thing in the text
+ segment.
+
+ Note that the code in the .init section has already been run.
+ This includes _init and _libc_init
+
+
+ At this entry point, most registers' values are unspecified, except:
+
+ x0 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.
+
+ sp The stack contains the arguments and environment:
+ 0(sp) argc
+ 8(sp) argv[0]
+ ...
+ (8*argc)(sp) NULL
+ (8*(argc+1))(sp) envp[0]
+ ...
+ NULL
+ */
+
+ .text
+ .globl _start
+ .type _start,#function
+_start:
+ /* Create an initial frame with 0 LR and FP */
+ mov x29, #0
+ mov x30, #0
+
+ /* Setup _fini in argument register */
+ mov x5, x0
+
+ /* Load argc and a pointer to argv */
+ ldr x1, [sp, #0]
+ add x2, sp, #8
+
+ /* Setup stack limit in argument register */
+ mov x6, sp
+
+#ifdef __PIC__
+ adrp x0, :got:main
+ ldr x0, [x0, #:got_lo12:main]
+
+ adrp x3, :got:_init
+ ldr x3, [x3, #:got_lo12:_init]
+
+ adrp x4, :got:_fini
+ ldr x4, [x4, #:got_lo12:_fini]
+#else
+ /* Set up the other arguments in registers */
+ ldr x0, =main
+ ldr x3, =_init
+ ldr x4, =_fini
+#endif
+
+ /* Let the libc call main and exit with its return code. */
+ bl __uClibc_main
+
+ /* should never get here....*/
+ bl abort
+
+ /* Define a symbol for the first piece of initialized data. */
+ .data
+ .globl __data_start
+__data_start:
+ .long 0
+ .weak data_start
+ data_start = __data_start
diff --git a/libc/sysdeps/linux/aarch64/crti.S b/libc/sysdeps/linux/aarch64/crti.S
new file mode 100644
index 000000000..49c57e4c4
--- /dev/null
+++ b/libc/sysdeps/linux/aarch64/crti.S
@@ -0,0 +1,59 @@
+/* Special .init and .fini section support for AArch64.
+ Copyright (C) 1995-2016 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.)
+
+ 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/>. */
+
+/* crti.S puts a function prologue at the beginning of the .init and
+ .fini sections and defines global symbols for those addresses, so
+ they can be called as functions. The symbols _init and _fini are
+ magic and cause the linker to emit DT_INIT and DT_FINI. */
+
+#include <libc-symbols.h>
+
+
+ .section .init,"ax",%progbits
+ .align 2
+ .global _init
+ .type _init, %function
+_init:
+ stp x29, x30, [sp, -16]!
+ mov x29, sp
+
+ .section .fini,"ax",%progbits
+ .align 2
+ .global _fini
+ .type _fini, %function
+_fini:
+ stp x29, x30, [sp, -16]!
+ mov x29, sp
diff --git a/libc/sysdeps/linux/aarch64/crtn.S b/libc/sysdeps/linux/aarch64/crtn.S
new file mode 100644
index 000000000..33d5f3d82
--- /dev/null
+++ b/libc/sysdeps/linux/aarch64/crtn.S
@@ -0,0 +1,46 @@
+/* Special .init and .fini section support for AArch64.
+ Copyright (C) 1995-2016 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.)
+
+ 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/>. */
+
+/* crtn.S puts function epilogues in the .init and .fini sections
+ corresponding to the prologues in crti.S. */
+
+ .section .init,"ax",%progbits
+ ldp x29, x30, [sp], 16
+ RET
+
+ .section .fini,"ax",%progbits
+ ldp x29, x30, [sp], 16
+ RET
diff --git a/libc/sysdeps/linux/aarch64/jmpbuf-offsets.h b/libc/sysdeps/linux/aarch64/jmpbuf-offsets.h
new file mode 100644
index 000000000..ab00cef26
--- /dev/null
+++ b/libc/sysdeps/linux/aarch64/jmpbuf-offsets.h
@@ -0,0 +1,57 @@
+/* Copyright (C) 2006-2016 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/>. */
+
+#define JB_X19 0
+#define JB_X20 1
+#define JB_X21 2
+#define JB_X22 3
+#define JB_X23 4
+#define JB_X24 5
+#define JB_X25 6
+#define JB_X26 7
+#define JB_X27 8
+#define JB_X28 9
+#define JB_X29 10
+#define JB_LR 11
+#define JB_SP 13
+
+#define JB_D8 14
+#define JB_D9 15
+#define JB_D10 16
+#define JB_D11 17
+#define JB_D12 18
+#define JB_D13 19
+#define JB_D14 20
+#define JB_D15 21
+
+#ifndef __ASSEMBLER__
+#include <setjmp.h>
+#include <stdint.h>
+#include <sysdep.h>
+
+static inline uintptr_t __attribute__ ((unused))
+_jmpbuf_sp (__jmp_buf jmpbuf)
+{
+ uintptr_t sp = jmpbuf[JB_SP];
+ return sp;
+}
+#endif
+
+/* Helper for generic ____longjmp_chk(). */
+#define JB_FRAME_ADDRESS(buf) \
+ ((void *) _jmpbuf_sp (buf))
diff --git a/libc/sysdeps/linux/aarch64/jmpbuf-unwind.h b/libc/sysdeps/linux/aarch64/jmpbuf-unwind.h
new file mode 100644
index 000000000..77bad1d41
--- /dev/null
+++ b/libc/sysdeps/linux/aarch64/jmpbuf-unwind.h
@@ -0,0 +1,34 @@
+/* Copyright (C) 2005-2016 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/>. */
+
+#include <setjmp.h>
+#include <jmpbuf-offsets.h>
+#include <stdint.h>
+#include <unwind.h>
+
+/* Test if longjmp to JMPBUF would unwind the frame
+ containing a local variable at ADDRESS. */
+#define _JMPBUF_UNWINDS(jmpbuf, address, demangle) \
+ ((void *) (address) < (void *) demangle (jmpbuf[JB_SP]))
+
+#define _JMPBUF_CFA_UNWINDS_ADJ(jmpbuf, context, adj) \
+ _JMPBUF_UNWINDS_ADJ (jmpbuf, (void *) _Unwind_GetCFA (context), adj)
+
+#define _JMPBUF_UNWINDS_ADJ(_jmpbuf, _address, _adj) \
+ ((uintptr_t) (_address) - (_adj) < _jmpbuf_sp (_jmpbuf) - (_adj))
+
diff --git a/libc/sysdeps/linux/aarch64/setjmp.S b/libc/sysdeps/linux/aarch64/setjmp.S
new file mode 100644
index 000000000..b3d616222
--- /dev/null
+++ b/libc/sysdeps/linux/aarch64/setjmp.S
@@ -0,0 +1,59 @@
+/* Copyright (C) 1997-2016 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/>. */
+
+#include <sysdep.h>
+#include <jmpbuf-offsets.h>
+
+ /* Keep traditional entry points in with sigsetjmp(). */
+ENTRY (setjmp)
+ mov x1, #1
+ b 1f
+END (setjmp)
+
+ENTRY (_setjmp)
+ mov x1, #0
+ b 1f
+END (_setjmp)
+libc_hidden_def (_setjmp)
+
+ENTRY (__sigsetjmp)
+
+1:
+ stp x19, x20, [x0, #JB_X19<<3]
+ stp x21, x22, [x0, #JB_X21<<3]
+ stp x23, x24, [x0, #JB_X23<<3]
+ stp x25, x26, [x0, #JB_X25<<3]
+ stp x27, x28, [x0, #JB_X27<<3]
+
+ stp x29, x30, [x0, #JB_X29<<3]
+
+ /* setjmp probe takes 3 arguments, address of jump buffer
+ first argument (8@x0), return value second argument (-4@x1),
+ and target address (8@x30), respectively. */
+ //LIBC_PROBE (setjmp, 3, 8@x0, -4@x1, 8@x30)
+ stp d8, d9, [x0, #JB_D8<<3]
+ stp d10, d11, [x0, #JB_D10<<3]
+ stp d12, d13, [x0, #JB_D12<<3]
+ stp d14, d15, [x0, #JB_D14<<3]
+ mov x2, sp
+ str x2, [x0, #JB_SP<<3]
+
+ b C_SYMBOL_NAME(__sigjmp_save)
+
+END (__sigsetjmp)
+hidden_def (__sigsetjmp)
diff --git a/libc/sysdeps/linux/aarch64/sys/procfs.h b/libc/sysdeps/linux/aarch64/sys/procfs.h
new file mode 100644
index 000000000..7e408c3f8
--- /dev/null
+++ b/libc/sysdeps/linux/aarch64/sys/procfs.h
@@ -0,0 +1,123 @@
+/* Copyright (C) 1996-2016 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_PROCFS_H
+#define _SYS_PROCFS_H 1
+
+/* This is somewhat modelled after the file of the same name on SVR4
+ systems. It provides a definition of the core file format for ELF
+ used on Linux. It doesn't have anything to do with the /proc file
+ system, even though Linux has one.
+
+ Anyway, the whole purpose of this file is for GDB and GDB only.
+ Don't read too much into it. Don't use it for anything other than
+ GDB unless you know what you are doing. */
+
+#include <features.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/user.h>
+
+__BEGIN_DECLS
+
+/* Type for a general-purpose register. */
+typedef unsigned long elf_greg_t;
+
+/* And the whole bunch of them. We could have used `struct
+ pt_regs' directly in the typedef, but tradition says that
+ the register set is an array, which does have some peculiar
+ semantics, so leave it that way. */
+#define ELF_NGREG (sizeof (struct user_regs_struct) / sizeof(elf_greg_t))
+typedef elf_greg_t elf_gregset_t[ELF_NGREG];
+
+/* Register set for the floating-point registers. */
+typedef struct user_fpsimd_struct elf_fpregset_t;
+
+/* Signal info. */
+struct elf_siginfo
+ {
+ int si_signo; /* Signal number. */
+ int si_code; /* Extra code. */
+ int si_errno; /* Errno. */
+ };
+
+/* Definitions to generate Intel SVR4-like core files. These mostly
+ have the same names as the SVR4 types with "elf_" tacked on the
+ front to prevent clashes with Linux definitions, and the typedef
+ forms have been avoided. This is mostly like the SVR4 structure,
+ but more Linuxy, with things that Linux does not support and which
+ GDB doesn't really use excluded. */
+
+struct elf_prstatus
+ {
+ struct elf_siginfo pr_info; /* Info associated with signal. */
+ short int pr_cursig; /* Current signal. */
+ unsigned long int pr_sigpend; /* Set of pending signals. */
+ unsigned long int pr_sighold; /* Set of held signals. */
+ __pid_t pr_pid;
+ __pid_t pr_ppid;
+ __pid_t pr_pgrp;
+ __pid_t pr_sid;
+ struct timeval pr_utime; /* User time. */
+ struct timeval pr_stime; /* System time. */
+ struct timeval pr_cutime; /* Cumulative user time. */
+ struct timeval pr_cstime; /* Cumulative system time. */
+ elf_gregset_t pr_reg; /* GP registers. */
+ int pr_fpvalid; /* True if math copro being used. */
+ };
+
+
+#define ELF_PRARGSZ (80) /* Number of chars for args. */
+
+struct elf_prpsinfo
+ {
+ char pr_state; /* Numeric process state. */
+ char pr_sname; /* Char for pr_state. */
+ char pr_zomb; /* Zombie. */
+ char pr_nice; /* Nice val. */
+ unsigned long int pr_flag; /* Flags. */
+ unsigned int pr_uid;
+ unsigned int pr_gid;
+ int pr_pid, pr_ppid, pr_pgrp, pr_sid;
+ /* Lots missing */
+ char pr_fname[16]; /* Filename of executable. */
+ char pr_psargs[ELF_PRARGSZ]; /* Initial part of arg list. */
+ };
+
+/* The rest of this file provides the types for emulation of the
+ Solaris <proc_service.h> interfaces that should be implemented by
+ users of libthread_db. */
+
+/* Addresses. */
+typedef void *psaddr_t;
+
+/* Register sets. Linux has different names. */
+typedef elf_gregset_t prgregset_t;
+typedef elf_fpregset_t prfpregset_t;
+
+/* We don't have any differences between processes and threads,
+ therefore have only one PID type. */
+typedef __pid_t lwpid_t;
+
+/* Process status and info. In the end we do provide typedefs for them. */
+typedef struct elf_prstatus prstatus_t;
+typedef struct elf_prpsinfo prpsinfo_t;
+
+__END_DECLS
+
+#endif /* sys/procfs.h */
diff --git a/libc/sysdeps/linux/aarch64/sys/ucontext.h b/libc/sysdeps/linux/aarch64/sys/ucontext.h
new file mode 100644
index 000000000..d17458896
--- /dev/null
+++ b/libc/sysdeps/linux/aarch64/sys/ucontext.h
@@ -0,0 +1,53 @@
+/* Copyright (C) 1998-2016 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/>. */
+
+/* System V/AArch64 ABI compliant context switching support. */
+
+#ifndef _SYS_UCONTEXT_H
+#define _SYS_UCONTEXT_H 1
+
+#include <features.h>
+#include <signal.h>
+
+#include <sys/procfs.h>
+
+typedef elf_greg_t greg_t;
+
+/* Container for all general registers. */
+typedef elf_gregset_t gregset_t;
+
+/* Structure to describe FPU registers. */
+typedef elf_fpregset_t fpregset_t;
+
+/* Context to describe whole processor state. This only describes
+ the core registers; coprocessor registers get saved elsewhere
+ (e.g. in uc_regspace, or somewhere unspecified on the stack
+ during non-RT signal handlers). */
+typedef struct sigcontext mcontext_t;
+
+/* Userlevel context. */
+typedef struct ucontext
+ {
+ unsigned long uc_flags;
+ struct ucontext *uc_link;
+ stack_t uc_stack;
+ __sigset_t uc_sigmask;
+ mcontext_t uc_mcontext;
+ } ucontext_t;
+
+#endif /* sys/ucontext.h */
diff --git a/libc/sysdeps/linux/aarch64/sys/user.h b/libc/sysdeps/linux/aarch64/sys/user.h
new file mode 100644
index 000000000..f6fc361e8
--- /dev/null
+++ b/libc/sysdeps/linux/aarch64/sys/user.h
@@ -0,0 +1,37 @@
+/* Copyright (C) 2009-2016 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_USER_H
+#define _SYS_USER_H 1
+
+struct user_regs_struct
+{
+ unsigned long long regs[31];
+ unsigned long long sp;
+ unsigned long long pc;
+ unsigned long long pstate;
+};
+
+struct user_fpsimd_struct
+{
+ __uint128_t vregs[32];
+ unsigned int fpsr;
+ unsigned int fpcr;
+};
+
+#endif
diff --git a/libc/sysdeps/linux/aarch64/syscall.S b/libc/sysdeps/linux/aarch64/syscall.S
new file mode 100644
index 000000000..ac609a337
--- /dev/null
+++ b/libc/sysdeps/linux/aarch64/syscall.S
@@ -0,0 +1,42 @@
+/* Copyright (C) 2005-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 <sysdep.h>
+
+/* syscall (int nr, ...)
+
+ AArch64 system calls take between 0 and 7 arguments. On entry here nr
+ is in w0 and any other system call arguments are in register x1..x7.
+
+ For kernel entry we need to move the system call nr to x8 then
+ load the remaining arguments to register. */
+
+ENTRY (syscall)
+ uxtw x8, w0
+ mov x0, x1
+ mov x1, x2
+ mov x2, x3
+ mov x3, x4
+ mov x4, x5
+ mov x5, x6
+ mov x6, x7
+ svc 0x0
+ cmn x0, #4095
+ b.cs 1f
+ RET
+1:
+ b SYSCALL_ERROR
+PSEUDO_END (syscall)
diff --git a/libc/sysdeps/linux/aarch64/sysdep.h b/libc/sysdeps/linux/aarch64/sysdep.h
new file mode 100644
index 000000000..82790be6d
--- /dev/null
+++ b/libc/sysdeps/linux/aarch64/sysdep.h
@@ -0,0 +1,150 @@
+/* Copyright (C) 2005-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 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 _LINUX_AARCH64_SYSDEP_H
+#define _LINUX_AARCH64_SYSDEP_H 1
+
+#include <common/sysdep.h>
+#include <sys/syscall.h>
+
+/* In order to get __set_errno() definition in INLINE_SYSCALL. */
+#ifndef __ASSEMBLER__
+#include <errno.h>
+#endif
+
+/* For Linux we can use the system call table in the header file
+/usr/include/asm/unistd.h
+of the kernel. But these symbols do not follow the SYS_* syntax
+so we have to redefine the `SYS_ify' macro here. */
+#undef SYS_ify
+#define SYS_ify(syscall_name) (__NR_##syscall_name)
+
+#ifdef __ASSEMBLER__
+
+#define ASM_SIZE_DIRECTIVE(name) .size name,.-name
+
+/* Local label name for asm code. */
+#ifndef L
+# define L(name) .L##name
+#endif
+
+/* Define an entry point visible from C. */
+#define ENTRY(name) \
+ .globl C_SYMBOL_NAME(name); \
+ .type C_SYMBOL_NAME(name),%function; \
+ .align 4; \
+ C_LABEL(name) \
+ cfi_startproc;
+
+/* Define an entry point visible from C. */
+#define ENTRY_ALIGN(name, align) \
+ .globl C_SYMBOL_NAME(name); \
+ .type C_SYMBOL_NAME(name),%function; \
+ .p2align align; \
+ C_LABEL(name) \
+ cfi_startproc;
+
+#undef END
+#define END(name) \
+ cfi_endproc; \
+ ASM_SIZE_DIRECTIVE(name)
+
+/* Linux uses a negative return value to indicate syscall errors,
+unlike most Unices, which use the condition codes' carry flag.
+
+Since version 2.1 the return value of a system call might be
+negative even if the call succeeded. E.g., the `lseek' system call
+might return a large offset. Therefore we must not anymore test
+for < 0, but test for a real error by making sure the value in R0
+is a real error number. Linus said he will make sure the no syscall
+returns a value in -1 .. -4095 as a valid result so we can safely
+test with -4095. */
+
+# undef PSEUDO
+# define PSEUDO(name, syscall_name, args) \
+.text; \
+ENTRY (name); \
+DO_CALL (syscall_name, args); \
+cmn x0, #4095; \
+b.cs .Lsyscall_error;
+
+# undef PSEUDO_END
+# define PSEUDO_END(name) \
+SYSCALL_ERROR_HANDLER \
+END (name)
+
+# undef PSEUDO_NOERRNO
+# define PSEUDO_NOERRNO(name, syscall_name, args) \
+.text; \
+ENTRY (name); \
+DO_CALL (syscall_name, args);
+
+# undef PSEUDO_END_NOERRNO
+# define PSEUDO_END_NOERRNO(name) \
+END (name)
+
+# define ret_NOERRNO ret
+
+/* The function has to return the error code. */
+# undef PSEUDO_ERRVAL
+# define PSEUDO_ERRVAL(name, syscall_name, args) \
+.text; \
+ENTRY (name) \
+DO_CALL (syscall_name, args); \
+neg x0, x0
+
+# undef PSEUDO_END_ERRVAL
+# define PSEUDO_END_ERRVAL(name) \
+END (name)
+
+# define ret_ERRVAL ret
+
+#if defined _LIBC_REENTRANT
+# if defined USE___THREAD
+# ifndef NOT_IN_libc
+# define SYSCALL_ERROR_ERRNO __libc_errno
+# else
+# define SYSCALL_ERROR_ERRNO errno
+# endif
+# endif
+#endif
+
+#if defined USE___THREAD
+# define SYSCALL_ERROR .Lsyscall_error
+# define SYSCALL_ERROR_HANDLER \
+.Lsyscall_error: \
+ adrp x1, :gottprel:SYSCALL_ERROR_ERRNO; \
+ neg w2, w0; \
+ ldr x1, [x1, :gottprel_lo12:SYSCALL_ERROR_ERRNO]; \
+ mrs x3, tpidr_el0; \
+ mov x0, -1; \
+ str w2, [x1, x3]; \
+ ret;
+#else
+# define SYSCALL_ERROR __syscall_error
+# define SYSCALL_ERROR_HANDLER \
+.Lsyscall_error: \
+ b __syscall_error;
+#endif
+
+# undef DO_CALL
+# define DO_CALL(syscall_name, args) \
+mov x8, SYS_ify (syscall_name); \
+svc 0
+
+#endif /* __ASSEMBLER__ */
+
+#endif /* linux/aarch64/sysdep.h */
diff --git a/libc/sysdeps/linux/aarch64/vfork.S b/libc/sysdeps/linux/aarch64/vfork.S
new file mode 100644
index 000000000..9a8fd469a
--- /dev/null
+++ b/libc/sysdeps/linux/aarch64/vfork.S
@@ -0,0 +1,37 @@
+/* Copyright (C) 1999-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 <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)
+
+ mov x0, #0x4111 /* CLONE_VM | CLONE_VFORK | SIGCHLD */
+ mov x1, sp
+ DO_CALL (clone, 2)
+
+ cmn x0, #4095
+ b.cs .Lsyscall_error
+ RET
+
+PSEUDO_END (vfork)
+libc_hidden_def (vfork)
diff --git a/libc/sysdeps/linux/common-generic/bits/stat.h b/libc/sysdeps/linux/common-generic/bits/stat.h
index 945c408a0..0f66fc0e7 100644
--- a/libc/sysdeps/linux/common-generic/bits/stat.h
+++ b/libc/sysdeps/linux/common-generic/bits/stat.h
@@ -30,45 +30,6 @@
*/
struct stat
{
-#ifndef __USE_FILE_OFFSET64
-# if __BYTE_ORDER == __LITTLE_ENDIAN
- unsigned long st_dev; /* Device. */
- unsigned long __pad1;
- unsigned long st_ino; /* 32bit file serial number. */
- unsigned long __pad2;
- unsigned int st_mode; /* File mode. */
- unsigned int st_nlink; /* Link count. */
- unsigned int st_uid; /* User ID of the file's owner. */
- unsigned int st_gid; /* Group ID of the file's group.*/
- unsigned long st_rdev; /* Device number, if device. */
- unsigned long __pad3;
- unsigned long long __pad4;
- long st_size; /* SIze of file, in bytes. */
- long __pad5;
- int st_blksize; /* Optimal block size for I/O. */
- int __pad6;
- long st_blocks; /* Number 512-byte blocks allocated */
- long __pad7;
-# else
- unsigned long __pad1;
- unsigned long st_dev; /* Device. */
- unsigned long __pad2;
- unsigned long st_ino; /* 32bit file serial number. */
- unsigned int st_mode; /* File mode. */
- unsigned int st_nlink; /* Link count. */
- unsigned int st_uid; /* User ID of the file's owner. */
- unsigned int st_gid; /* Group ID of the file's group.*/
- unsigned long __pad3;
- unsigned long st_rdev; /* Device number, if device. */
- unsigned long long __pad4;
- long __pad5;
- long st_size; /* Size of file, in bytes. */
- int st_blksize; /* Optimal block size for I/O. */
- int __pad6;
- long __pad7;
- long st_blocks; /* Number 512-byte blocks allocated */
-# endif /* __LITTLE_ENDIAN */
-#else
unsigned long long st_dev; /* Device. */
unsigned long long st_ino; /* 32bit file serial number. */
unsigned int st_mode; /* File mode. */
@@ -81,7 +42,6 @@ struct stat
int st_blksize; /* Optimal block size for I/O. */
int __pad2;
long long st_blocks; /* Number 512-byte blocks allocated */
-#endif
#ifdef __USE_MISC
/* Nanosecond resolution timestamps are stored in a format
equivalent to 'struct timespec'. This is the type used
@@ -96,21 +56,12 @@ struct stat
# define st_mtime st_mtim.tv_sec
# define st_ctime st_ctim.tv_sec
#else
-# ifndef __USE_FILE_OFFSET64
- long st_atime; /* Time of last access. */
- unsigned long st_atime_nsec;
- long st_mtime; /* Time of last modification. */
- unsigned long st_mtime_nsec;
- long st_ctime; /* Time of last status change. */
- unsigned long st_ctime_nsec;
-# else
int st_atime; /* Time of last access. */
unsigned int st_atime_nsec;
int st_mtime; /* Time of last modification. */
unsigned int st_mtime_nsec;
int st_ctime; /* Time of last status change. */
unsigned int st_ctime_nsec;
-# endif
#endif
unsigned int __unused4;
unsigned int __unused5;
diff --git a/libc/sysdeps/linux/common/fstat.c b/libc/sysdeps/linux/common/fstat.c
index eae3c8006..ac77eb295 100644
--- a/libc/sysdeps/linux/common/fstat.c
+++ b/libc/sysdeps/linux/common/fstat.c
@@ -7,25 +7,26 @@
* Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
*/
-#include <sys/syscall.h>
+#include <features.h>
#include <unistd.h>
#include <sys/stat.h>
+#include <sys/syscall.h>
+
#include "xstatconv.h"
#if defined __NR_fstat64 && !defined __NR_fstat
int fstat(int fd, struct stat *buf)
{
- int result = INLINE_SYSCALL(fstat64, 2, fd, buf);
- if (result == 0) {
- /* Did we overflow? */
- if (buf->__pad1 || buf->__pad2 || buf->__pad3
- || buf->__pad4 || buf->__pad5
- || buf->__pad6 || buf->__pad7) {
- __set_errno(EOVERFLOW);
- return -1;
- }
- }
- return result;
+ return INLINE_SYSCALL(fstat64, 2, fd, buf);
+}
+libc_hidden_def(fstat)
+
+#elif __WORDSIZE == 64 && defined __NR_newfstatat
+#include <fcntl.h>
+
+int fstat(int fd, struct stat *buf)
+{
+ return INLINE_SYSCALL(fstat, 2, fd, buf);
}
libc_hidden_def(fstat)
@@ -55,10 +56,9 @@ int fstat(int fd, struct stat *buf)
return result;
}
libc_hidden_def(fstat)
+#endif
# if ! defined __NR_fstat64
strong_alias_untyped(fstat,fstat64)
libc_hidden_def(fstat64)
-# endif
-
#endif
diff --git a/libc/sysdeps/linux/common/fstatat.c b/libc/sysdeps/linux/common/fstatat.c
index 4006814f0..13673d76c 100644
--- a/libc/sysdeps/linux/common/fstatat.c
+++ b/libc/sysdeps/linux/common/fstatat.c
@@ -26,15 +26,6 @@ int fstatat(int fd, const char *file, struct stat *buf, int flag)
__xstat32_conv(&kbuf, buf);
# else
ret = INLINE_SYSCALL(fstatat64, 4, fd, file, buf, flag);
- if (ret == 0) {
- /* Did we overflow */
- if (buf->__pad1 || buf->__pad2 || buf->__pad3
- || buf->__pad4 || buf->__pad5 || buf->__pad6
- || buf->__pad7) {
- __set_errno(EOVERFLOW);
- return -1;
- }
- }
# endif /* __ARCH_HAS_DEPRECATED_SYSCALLS__ */
return ret;
}
diff --git a/libc/sysdeps/linux/common/lstat.c b/libc/sysdeps/linux/common/lstat.c
index 143cc1916..cef9b463d 100644
--- a/libc/sysdeps/linux/common/lstat.c
+++ b/libc/sysdeps/linux/common/lstat.c
@@ -20,6 +20,15 @@ int lstat(const char *file_name, struct stat *buf)
}
libc_hidden_def(lstat)
+#elif __WORDSIZE == 64 && defined __NR_newfstatat
+# include <fcntl.h>
+
+int lstat(const char *file_name, struct stat *buf)
+{
+ return fstatat(AT_FDCWD, file_name, buf, AT_SYMLINK_NOFOLLOW);
+}
+libc_hidden_def(lstat)
+
/* For systems which have both, prefer the old one */
#else
# include "xstatconv.h"
diff --git a/libc/sysdeps/linux/common/lstat64.c b/libc/sysdeps/linux/common/lstat64.c
index c43e53e1d..76637b556 100644
--- a/libc/sysdeps/linux/common/lstat64.c
+++ b/libc/sysdeps/linux/common/lstat64.c
@@ -9,11 +9,19 @@
#include <_lfs_64.h>
#include <sys/syscall.h>
+#include <unistd.h>
+#include <sys/stat.h>
-# include <unistd.h>
-# include <sys/stat.h>
+#if defined __NR_fstatat64 && !defined __NR_lstat
+# include <fcntl.h>
+
+int lstat64(const char *file_name, struct stat64 *buf)
+{
+ return fstatat64(AT_FDCWD, file_name, buf, AT_SYMLINK_NOFOLLOW);
+}
+libc_hidden_def(lstat64)
-#if defined __NR_fstatat64 && !defined __NR_lstat64
+#elif __WORDSIZE == 64 && defined __NR_newfstatat
# include <fcntl.h>
int lstat64(const char *file_name, struct stat64 *buf)
diff --git a/libc/sysdeps/linux/common/stat.c b/libc/sysdeps/linux/common/stat.c
index b3c2a19ea..8e4542a74 100644
--- a/libc/sysdeps/linux/common/stat.c
+++ b/libc/sysdeps/linux/common/stat.c
@@ -21,6 +21,14 @@ int stat(const char *file_name, struct stat *buf)
return fstatat(AT_FDCWD, file_name, buf, 0);
}
+#elif __WORDSIZE == 64 && defined __NR_newfstatat
+# include <fcntl.h>
+
+int stat(const char *file_name, struct stat *buf)
+{
+ return fstatat64(AT_FDCWD, file_name, buf, 0);
+}
+
#else
# include "xstatconv.h"
diff --git a/libpthread/nptl/sysdeps/aarch64/Makefile.arch b/libpthread/nptl/sysdeps/aarch64/Makefile.arch
new file mode 100644
index 000000000..d6d3cbf4a
--- /dev/null
+++ b/libpthread/nptl/sysdeps/aarch64/Makefile.arch
@@ -0,0 +1,32 @@
+# Copyright (C) 2012 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; see the file COPYING.LIB. If
+# not, see <http://www.gnu.org/licenses/>.
+
+ASFLAGS-dl-tlsdesc.S = -DNOT_IN_libc=1
+
+libc_arch_a_CSRC = libc-tls.c
+libc_arch_a_SSRC = libc-dl-tlsdesc.S
+
+CFLAGS-gen_tlsdesc.c = -S
+$(libpthread_arch_OUT)/gen_tlsdesc.c: $(libpthread_arch_DIR)/tlsdesc.sym | $(libpthread_arch_OUT)
+ $(do_awk) $(top_srcdir)extra/scripts/gen-as-const.awk $< > $@
+$(libpthread_arch_OUT)/gen_tlsdesc.s: $(libpthread_arch_OUT)/gen_tlsdesc.c | headers
+ $(compile.c)
+libpthread-generated-y += $(libpthread_arch_OUT)/gen_tlsdesc.s
+$(libpthread_arch_OUT)/tlsdesc.h: $(libpthread_arch_OUT)/gen_tlsdesc.s
+ $(do_sed) $(PTHREAD_GENERATE_MANGLE) $< > $@
+ @if test ! -s $@ ; then rm -f $@ ; false ; fi
+pregen-headers-$(UCLIBC_HAS_THREADS_NATIVE) += $(libpthread_arch_OUT)/tlsdesc.h
diff --git a/libpthread/nptl/sysdeps/aarch64/dl-tls.h b/libpthread/nptl/sysdeps/aarch64/dl-tls.h
new file mode 100644
index 000000000..e5cd8cca3
--- /dev/null
+++ b/libpthread/nptl/sysdeps/aarch64/dl-tls.h
@@ -0,0 +1,55 @@
+/* Copyright (C) 2005-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/>. */
+
+#ifndef _AARCH64_DL_TLS_H
+#define _AARCH64_DL_TLS_H 1
+
+/* Type used to represent a TLS descriptor in the GOT. */
+struct tlsdesc
+{
+ ptrdiff_t (*entry) (struct tlsdesc *);
+ void *arg;
+};
+
+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 *);
+
+# ifdef SHARED
+extern void *_dl_make_tlsdesc_dynamic (struct link_map *, size_t);
+
+extern ptrdiff_t attribute_hidden
+_dl_tlsdesc_dynamic (struct tlsdesc *);
+# endif
+
+extern void *__tls_get_addr (tls_index *ti);
+
+#define TLS_DTV_UNALLOCATED ((void *) -1l)
+
+#endif
diff --git a/libpthread/nptl/sysdeps/aarch64/libc-dl-tlsdesc.S b/libpthread/nptl/sysdeps/aarch64/libc-dl-tlsdesc.S
new file mode 100644
index 000000000..fd408d845
--- /dev/null
+++ b/libpthread/nptl/sysdeps/aarch64/libc-dl-tlsdesc.S
@@ -0,0 +1 @@
+#include <ldso/ldso/aarch64/dl-tlsdesc.S>
diff --git a/libpthread/nptl/sysdeps/aarch64/libc-tls.c b/libpthread/nptl/sysdeps/aarch64/libc-tls.c
new file mode 100644
index 000000000..4e2bd3731
--- /dev/null
+++ b/libpthread/nptl/sysdeps/aarch64/libc-tls.c
@@ -0,0 +1,35 @@
+/* Thread-local storage handling in the ELF dynamic linker. AARCH64 version.
+ Copyright (C) 2005 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 <sysdeps/generic/libc-tls.c>
+#include <dl-tls.h>
+
+#if defined(USE_TLS) && USE_TLS
+
+/* On AARCH64, 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 + ti->ti_offset;
+}
+
+#endif
diff --git a/libpthread/nptl/sysdeps/aarch64/pthread_spin_lock.c b/libpthread/nptl/sysdeps/aarch64/pthread_spin_lock.c
new file mode 100644
index 000000000..cec3acbc6
--- /dev/null
+++ b/libpthread/nptl/sysdeps/aarch64/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 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 <atomic.h>
+#include "pthreadP.h"
+
+/* A machine-specific version can define SPIN_LOCK_READS_BETWEEN_CMPXCHG
+ to the number of plain reads that it's optimal to spin on between uses
+ of atomic_compare_and_exchange_val_acq. If spinning forever is optimal
+ then use -1. If no plain reads here would ever be optimal, use 0. */
+#define SPIN_LOCK_READS_BETWEEN_CMPXCHG 1000
+
+int
+pthread_spin_lock (pthread_spinlock_t *lock)
+{
+ /* atomic_exchange usually takes less instructions than
+ atomic_compare_and_exchange. On the other hand,
+ atomic_compare_and_exchange potentially generates less bus traffic
+ when the lock is locked.
+ We assume that the first try mostly will be successful, and we use
+ atomic_exchange. For the subsequent tries we use
+ atomic_compare_and_exchange. */
+ if (atomic_exchange_acq (lock, 1) == 0)
+ return 0;
+
+ do
+ {
+ /* The lock is contended and we need to wait. Going straight back
+ to cmpxchg is not a good idea on many targets as that will force
+ expensive memory synchronizations among processors and penalize other
+ running threads.
+ On the other hand, we do want to update memory state on the local core
+ once in a while to avoid spinning indefinitely until some event that
+ will happen to update local memory as a side-effect. */
+ if (SPIN_LOCK_READS_BETWEEN_CMPXCHG >= 0)
+ {
+ int wait = SPIN_LOCK_READS_BETWEEN_CMPXCHG;
+
+ while (*lock != 0 && wait > 0)
+ --wait;
+ }
+ else
+ {
+ while (*lock != 0)
+ ;
+ }
+ }
+ while (atomic_compare_and_exchange_val_acq (lock, 1, 0) != 0);
+
+ return 0;
+}
diff --git a/libpthread/nptl/sysdeps/aarch64/pthread_spin_trylock.c b/libpthread/nptl/sysdeps/aarch64/pthread_spin_trylock.c
new file mode 100644
index 000000000..4e9aa64d3
--- /dev/null
+++ b/libpthread/nptl/sysdeps/aarch64/pthread_spin_trylock.c
@@ -0,0 +1,26 @@
+/* pthread_spin_trylock -- trylock 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 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 <errno.h>
+#include <atomic.h>
+#include "pthreadP.h"
+
+int
+pthread_spin_trylock (pthread_spinlock_t *lock)
+{
+ return atomic_exchange_acq (lock, 1) ? EBUSY : 0;
+}
diff --git a/libpthread/nptl/sysdeps/aarch64/pthreaddef.h b/libpthread/nptl/sysdeps/aarch64/pthreaddef.h
new file mode 100644
index 000000000..d9495f9cb
--- /dev/null
+++ b/libpthread/nptl/sysdeps/aarch64/pthreaddef.h
@@ -0,0 +1,34 @@
+/* Copyright (C) 2002-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/>. */
+
+/* Default stack size. */
+#define ARCH_STACK_DEFAULT_SIZE (2 * 1024 * 1024)
+
+/* Required stack pointer alignment at beginning. */
+#define STACK_ALIGN 16
+
+/* Minimal stack size after allocating thread descriptor and guard size. */
+#define MINIMAL_REST_STACK 2048
+
+/* Alignment requirement for TCB. */
+#define TCB_ALIGNMENT 16
+
+/* Location of current stack frame. */
+#define CURRENT_STACK_FRAME __builtin_frame_address (0)
+
+/* XXX Until we have a better place keep the definitions here. */
+#define __exit_thread_inline(val) \
+ INLINE_SYSCALL (exit, 1, (val))
diff --git a/libpthread/nptl/sysdeps/aarch64/tcb-offsets.sym b/libpthread/nptl/sysdeps/aarch64/tcb-offsets.sym
new file mode 100644
index 000000000..238647dd4
--- /dev/null
+++ b/libpthread/nptl/sysdeps/aarch64/tcb-offsets.sym
@@ -0,0 +1,6 @@
+#include <sysdep.h>
+#include <tls.h>
+
+PTHREAD_MULTIPLE_THREADS_OFFSET offsetof (struct pthread, header.multiple_threads)
+PTHREAD_TID_OFFSET offsetof (struct pthread, tid)
+PTHREAD_SIZEOF sizeof (struct pthread)
diff --git a/libpthread/nptl/sysdeps/aarch64/tls.h b/libpthread/nptl/sysdeps/aarch64/tls.h
new file mode 100644
index 000000000..5a88f6eff
--- /dev/null
+++ b/libpthread/nptl/sysdeps/aarch64/tls.h
@@ -0,0 +1,149 @@
+/* Copyright (C) 2005-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/>. */
+
+#ifndef _TLS_H
+#define _TLS_H 1
+
+#ifndef __ASSEMBLER__
+# include <stdbool.h>
+# include <stddef.h>
+# include <stdint.h>
+
+/* Type for the dtv. */
+typedef union dtv
+{
+ size_t counter;
+ struct
+ {
+ void *val;
+ bool is_static;
+ } pointer;
+} dtv_t;
+
+#else /* __ASSEMBLER__ */
+# include <tcb-offsets.h>
+#endif /* __ASSEMBLER__ */
+
+/* We require TLS support in the tools. */
+#define HAVE_TLS_SUPPORT 1
+#define HAVE_TLS_MODEL_ATTRIBUTE 1
+#define HAVE___THREAD 1
+
+/* Signal that TLS support is available. */
+#define USE_TLS 1
+
+#ifndef __ASSEMBLER__
+
+/* Get system call information. */
+# include <sysdep.h>
+
+/* The TP points to the start of the thread blocks. */
+# define TLS_DTV_AT_TP 1
+
+/* Get the thread descriptor definition. */
+# include <../../descr.h>
+
+typedef struct
+{
+ dtv_t *dtv;
+ void *private;
+} tcbhead_t;
+
+/* This is the size of the initial TCB. */
+# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t)
+
+/* Alignment requirements for the initial TCB. */
+# define TLS_INIT_TCB_ALIGN __alignof__ (struct pthread)
+
+/* This is the size of the TCB. */
+# define TLS_TCB_SIZE sizeof (tcbhead_t)
+
+/* This is the size we need before TCB. */
+# define TLS_PRE_TCB_SIZE sizeof (struct pthread)
+
+/* Alignment requirements for the TCB. */
+# define TLS_TCB_ALIGN __alignof__ (struct pthread)
+
+/* Install the dtv pointer. The pointer passed is to the element with
+ index -1 which contain the length. */
+# define INSTALL_DTV(tcbp, dtvp) \
+ (((tcbhead_t *) (tcbp))->dtv = (dtvp) + 1)
+
+/* Install new dtv for current thread. */
+# define INSTALL_NEW_DTV(dtv) \
+ (THREAD_DTV() = (dtv))
+
+/* Return dtv of given thread descriptor. */
+# define GET_DTV(tcbp) \
+ (((tcbhead_t *) (tcbp))->dtv)
+
+/* Code to initially initialize the thread pointer. This might need
+ special attention since 'errno' is not yet available and if the
+ operation can cause a failure 'errno' must not be touched. */
+# define TLS_INIT_TP(tcbp, secondcall) \
+ ({ __asm __volatile ("msr tpidr_el0, %0" : : "r" (tcbp)); NULL; })
+
+/* Value passed to 'clone' for initialization of the thread register. */
+# define TLS_DEFINE_INIT_TP(tp, pd) void *tp = (pd) + 1
+
+/* Return the address of the dtv for the current thread. */
+# define THREAD_DTV() \
+ (((tcbhead_t *) __builtin_thread_pointer ())->dtv)
+
+/* Return the thread descriptor for the current thread. */
+# define THREAD_SELF \
+ ((struct pthread *)__builtin_thread_pointer () - 1)
+
+/* Magic for libthread_db to know how to do THREAD_SELF. */
+# define DB_THREAD_SELF \
+ CONST_THREAD_AREA (64, sizeof (struct pthread))
+
+/* Access to data in the thread descriptor is easy. */
+# define THREAD_GETMEM(descr, member) \
+ descr->member
+# define THREAD_GETMEM_NC(descr, member, idx) \
+ descr->member[idx]
+# define THREAD_SETMEM(descr, member, value) \
+ descr->member = (value)
+# define THREAD_SETMEM_NC(descr, member, idx, value) \
+ descr->member[idx] = (value)
+
+/* Get and set the global scope generation counter in struct pthread. */
+# define THREAD_GSCOPE_FLAG_UNUSED 0
+# define THREAD_GSCOPE_FLAG_USED 1
+# define THREAD_GSCOPE_FLAG_WAIT 2
+# define THREAD_GSCOPE_RESET_FLAG() \
+ do \
+ { int __res \
+ = atomic_exchange_rel (&THREAD_SELF->header.gscope_flag, \
+ THREAD_GSCOPE_FLAG_UNUSED); \
+ if (__res == THREAD_GSCOPE_FLAG_WAIT) \
+ lll_futex_wake (&THREAD_SELF->header.gscope_flag, 1, LLL_PRIVATE); \
+ } \
+ while (0)
+# define THREAD_GSCOPE_SET_FLAG() \
+ do \
+ { \
+ THREAD_SELF->header.gscope_flag = THREAD_GSCOPE_FLAG_USED; \
+ atomic_write_barrier (); \
+ } \
+ while (0)
+# define THREAD_GSCOPE_WAIT() \
+ GL(dl_wait_lookup_done) ()
+
+# endif /* __ASSEMBLER__ */
+
+#endif /* tls.h */
diff --git a/libpthread/nptl/sysdeps/aarch64/tlsdesc.sym b/libpthread/nptl/sysdeps/aarch64/tlsdesc.sym
new file mode 100644
index 000000000..4d2d13761
--- /dev/null
+++ b/libpthread/nptl/sysdeps/aarch64/tlsdesc.sym
@@ -0,0 +1,17 @@
+#include <stddef.h>
+#include <sysdep.h>
+#include <tls.h>
+#include <link.h>
+#include <dl-tls.h>
+
+--
+
+-- Abuse tls.h macros to derive offsets relative to the thread register.
+
+TLSDESC_ARG offsetof(struct tlsdesc, arg)
+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)
+TCBHEAD_DTV offsetof(tcbhead_t, dtv)
+DTV_COUNTER offsetof(dtv_t, counter)
+TLS_DTV_UNALLOCATED TLS_DTV_UNALLOCATED
diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/aarch64/Makefile b/libpthread/nptl/sysdeps/unix/sysv/linux/aarch64/Makefile
new file mode 100644
index 000000000..729adf6f9
--- /dev/null
+++ b/libpthread/nptl/sysdeps/unix/sysv/linux/aarch64/Makefile
@@ -0,0 +1,13 @@
+# Makefile for uClibc NPTL
+#
+# Copyright (C) 2005 Steven J. Hill <sjhill@uclibc.org>
+#
+# Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in this tarball.
+#
+
+top_srcdir=../../../../../../../
+top_builddir=../../../../../../../
+all: objs
+include $(top_builddir)Rules.mak
+include Makefile.arch
+include $(top_srcdir)Makerules
diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/aarch64/Makefile.arch b/libpthread/nptl/sysdeps/unix/sysv/linux/aarch64/Makefile.arch
new file mode 100644
index 000000000..7d31efb21
--- /dev/null
+++ b/libpthread/nptl/sysdeps/unix/sysv/linux/aarch64/Makefile.arch
@@ -0,0 +1,14 @@
+# Makefile for uClibc NPTL
+#
+# Copyright (C) 2006 Steven J. Hill <sjhill@uclibc.org>
+#
+# Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in this tarball.
+#
+
+libpthread_linux_arch_SSRC =
+libpthread_linux_arch_CSRC = pthread_once.c
+
+libc_linux_arch_CSRC = fork.c
+
+CFLAGS += $(SSP_ALL_CFLAGS)
+
diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/aarch64/bits/pthreadtypes.h b/libpthread/nptl/sysdeps/unix/sysv/linux/aarch64/bits/pthreadtypes.h
new file mode 100644
index 000000000..47293a1a8
--- /dev/null
+++ b/libpthread/nptl/sysdeps/unix/sysv/linux/aarch64/bits/pthreadtypes.h
@@ -0,0 +1,174 @@
+/* Copyright (C) 2002-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/>. */
+
+#ifndef _BITS_PTHREADTYPES_H
+#define _BITS_PTHREADTYPES_H 1
+
+#include <endian.h>
+
+#define __SIZEOF_PTHREAD_ATTR_T 64
+#define __SIZEOF_PTHREAD_MUTEX_T 48
+#define __SIZEOF_PTHREAD_MUTEXATTR_T 8
+#define __SIZEOF_PTHREAD_COND_T 48
+#define __SIZEOF_PTHREAD_COND_COMPAT_T 48
+#define __SIZEOF_PTHREAD_CONDATTR_T 8
+#define __SIZEOF_PTHREAD_RWLOCK_T 56
+#define __SIZEOF_PTHREAD_RWLOCKATTR_T 8
+#define __SIZEOF_PTHREAD_BARRIER_T 32
+#define __SIZEOF_PTHREAD_BARRIERATTR_T 8
+
+#define __PTHREAD_RWLOCK_INT_FLAGS_SHARED 1
+
+/* Thread identifiers. The structure of the attribute type is not
+ exposed on purpose. */
+typedef unsigned long int pthread_t;
+
+
+union pthread_attr_t
+{
+ char __size[__SIZEOF_PTHREAD_ATTR_T];
+ long int __align;
+};
+#ifndef __have_pthread_attr_t
+typedef union pthread_attr_t pthread_attr_t;
+# define __have_pthread_attr_t1
+#endif
+
+typedef struct __pthread_internal_list
+{
+ struct __pthread_internal_list *__prev;
+ struct __pthread_internal_list *__next;
+} __pthread_list_t;
+
+
+/* Data structures for mutex handling. The structure of the attribute
+ type is not exposed on purpose. */
+typedef union
+{
+ struct __pthread_mutex_s
+ {
+ int __lock;
+ unsigned int __count;
+ int __owner;
+ unsigned int __nusers;
+ /* KIND must stay at this position in the structure to maintain
+ binary compatibility with static initializers. */
+ int __kind;
+ int __spins;
+ __pthread_list_t __list;
+#define __PTHREAD_MUTEX_HAVE_PREV 1
+ } __data;
+ char __size[__SIZEOF_PTHREAD_MUTEX_T];
+ long int __align;
+} pthread_mutex_t;
+
+/* Mutex __spins initializer used by PTHREAD_MUTEX_INITIALIZER. */
+#define __PTHREAD_SPINS 0
+
+typedef union
+{
+ char __size[__SIZEOF_PTHREAD_MUTEXATTR_T];
+ long int __align;
+} pthread_mutexattr_t;
+
+/* Data structure for conditional variable handling. The structure of
+ the attribute type is not exposed on purpose. */
+typedef union
+{
+ struct
+ {
+ int __lock;
+ unsigned int __futex;
+ __extension__ unsigned long long int __total_seq;
+ __extension__ unsigned long long int __wakeup_seq;
+ __extension__ unsigned long long int __woken_seq;
+ void *__mutex;
+ unsigned int __nwaiters;
+ unsigned int __broadcast_seq;
+ } __data;
+ char __size[__SIZEOF_PTHREAD_COND_T];
+ __extension__ long long int __align;
+} pthread_cond_t;
+
+typedef union
+{
+ char __size[__SIZEOF_PTHREAD_CONDATTR_T];
+ int __align;
+} pthread_condattr_t;
+
+
+/* Keys for thread-specific data */
+typedef unsigned int pthread_key_t;
+
+
+/* Once-only execution */
+typedef int pthread_once_t;
+
+
+#if defined __USE_UNIX98 || defined __USE_XOPEN2K
+/* Data structure for read-write lock variable handling. The
+ structure of the attribute type is not exposed on purpose. */
+typedef union
+{
+ struct
+ {
+ int __lock;
+ unsigned int __nr_readers;
+ unsigned int __readers_wakeup;
+ unsigned int __writer_wakeup;
+ unsigned int __nr_readers_queued;
+ unsigned int __nr_writers_queued;
+ int __writer;
+ int __shared;
+ unsigned long int __pad1;
+ unsigned long int __pad2;
+ unsigned int __flags;
+ } __data;
+ char __size[__SIZEOF_PTHREAD_RWLOCK_T];
+ long int __align;
+} pthread_rwlock_t;
+
+#define __PTHREAD_RWLOCK_ELISION_EXTRA 0
+
+typedef union
+{
+ char __size[__SIZEOF_PTHREAD_RWLOCKATTR_T];
+ long int __align;
+} pthread_rwlockattr_t;
+#endif
+
+
+#ifdef __USE_XOPEN2K
+/* POSIX spinlock data type. */
+typedef volatile int pthread_spinlock_t;
+
+
+/* POSIX barriers data type. The structure of the type is
+ deliberately not exposed. */
+typedef union
+{
+ char __size[__SIZEOF_PTHREAD_BARRIER_T];
+ long int __align;
+} pthread_barrier_t;
+
+typedef union
+{
+ char __size[__SIZEOF_PTHREAD_BARRIERATTR_T];
+ int __align;
+} pthread_barrierattr_t;
+#endif
+
+#endif /* bits/pthreadtypes.h */
diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/aarch64/bits/semaphore.h b/libpthread/nptl/sysdeps/unix/sysv/linux/aarch64/bits/semaphore.h
new file mode 100644
index 000000000..15a01beb1
--- /dev/null
+++ b/libpthread/nptl/sysdeps/unix/sysv/linux/aarch64/bits/semaphore.h
@@ -0,0 +1,30 @@
+/* Copyright (C) 2002-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/>. */
+
+#ifndef _SEMAPHORE_H
+# error "Never use <bits/semaphore.h> directly; include <semaphore.h> instead."
+#endif
+
+#define __SIZEOF_SEM_T 32
+
+/* Value returned if `sem_open' failed. */
+#define SEM_FAILED ((sem_t *) 0)
+
+typedef union
+{
+ char __size[__SIZEOF_SEM_T];
+ long long int __align;
+} sem_t;
diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/aarch64/createthread.c b/libpthread/nptl/sysdeps/unix/sysv/linux/aarch64/createthread.c
new file mode 100644
index 000000000..8157435db
--- /dev/null
+++ b/libpthread/nptl/sysdeps/unix/sysv/linux/aarch64/createthread.c
@@ -0,0 +1,21 @@
+/* Copyright (C) 2005 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/>. */
+
+/* Value passed to 'clone' for initialization of the thread register. */
+#define TLS_VALUE (pd + 1)
+
+/* Get the real implementation. */
+#include <sysdeps/pthread/createthread.c>
diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/aarch64/fork.c b/libpthread/nptl/sysdeps/unix/sysv/linux/aarch64/fork.c
new file mode 100644
index 000000000..c5d963aad
--- /dev/null
+++ b/libpthread/nptl/sysdeps/unix/sysv/linux/aarch64/fork.c
@@ -0,0 +1,11 @@
+#include <sched.h>
+#include <signal.h>
+#include <sysdep.h>
+#include <tls.h>
+
+#define ARCH_FORK() \
+ INLINE_SYSCALL (clone, 5, \
+ CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD, 0, \
+ NULL, NULL, &THREAD_SELF->tid)
+
+#include "../fork.c"
diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/aarch64/lowlevellock.h b/libpthread/nptl/sysdeps/unix/sysv/linux/aarch64/lowlevellock.h
new file mode 100644
index 000000000..6b0e51e99
--- /dev/null
+++ b/libpthread/nptl/sysdeps/unix/sysv/linux/aarch64/lowlevellock.h
@@ -0,0 +1,323 @@
+/* Copyright (C) 2005-2013 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/>. */
+
+#ifndef _LOWLEVELLOCK_H
+#define _LOWLEVELLOCK_H 1
+
+#include <time.h>
+#include <sys/param.h>
+#include <bits/pthreadtypes.h>
+#include <atomic.h>
+#include <sysdep.h>
+#include <bits/kernel-features.h>
+
+
+#define FUTEX_WAIT 0
+#define FUTEX_WAKE 1
+#define FUTEX_REQUEUE 3
+#define FUTEX_CMP_REQUEUE 4
+#define FUTEX_WAKE_OP 5
+#define FUTEX_OP_CLEAR_WAKE_IF_GT_ONE ((4 << 24) | 1)
+#define FUTEX_LOCK_PI 6
+#define FUTEX_UNLOCK_PI 7
+#define FUTEX_TRYLOCK_PI 8
+#define FUTEX_WAIT_BITSET 9
+#define FUTEX_WAKE_BITSET 10
+#define FUTEX_WAIT_REQUEUE_PI 11
+#define FUTEX_CMP_REQUEUE_PI 12
+#define FUTEX_PRIVATE_FLAG 128
+#define FUTEX_CLOCK_REALTIME 256
+
+#define FUTEX_BITSET_MATCH_ANY 0xffffffff
+
+/* Values for 'private' parameter of locking macros. Yes, the
+ definition seems to be backwards. But it is not. The bit will be
+ reversed before passing to the system call. */
+#define LLL_PRIVATE 0
+#define LLL_SHARED FUTEX_PRIVATE_FLAG
+
+
+#if !defined NOT_IN_libc || defined IS_IN_rtld
+/* In libc.so or ld.so all futexes are private. */
+# ifdef __ASSUME_PRIVATE_FUTEX
+# define __lll_private_flag(fl, private) \
+ ((fl) | FUTEX_PRIVATE_FLAG)
+# else
+# define __lll_private_flag(fl, private) \
+ ((fl) | THREAD_GETMEM (THREAD_SELF, header.private_futex))
+# endif
+#else
+# ifdef __ASSUME_PRIVATE_FUTEX
+# define __lll_private_flag(fl, private) \
+ (((fl) | FUTEX_PRIVATE_FLAG) ^ (private))
+# else
+# define __lll_private_flag(fl, private) \
+ (__builtin_constant_p (private) \
+ ? ((private) == 0 \
+ ? ((fl) | THREAD_GETMEM (THREAD_SELF, header.private_futex)) \
+ : (fl)) \
+ : ((fl) | (((private) ^ FUTEX_PRIVATE_FLAG) \
+ & THREAD_GETMEM (THREAD_SELF, header.private_futex))))
+# endif
+#endif
+
+
+#define lll_futex_wait(futexp, val, private) \
+ lll_futex_timed_wait(futexp, val, NULL, private)
+
+#define lll_futex_timed_wait(futexp, val, timespec, private) \
+ ({ \
+ long int __ret; \
+ INTERNAL_SYSCALL_DECL (__err); \
+ __ret = INTERNAL_SYSCALL (futex, __err, 4, (futexp), \
+ __lll_private_flag (FUTEX_WAIT, private), \
+ (val), (timespec)); \
+ __ret; \
+ })
+
+#define lll_futex_timed_wait_bitset(futexp, val, timespec, clockbit, private) \
+ ({ \
+ long int __ret; \
+ INTERNAL_SYSCALL_DECL (__err); \
+ int __op = FUTEX_WAIT_BITSET | clockbit; \
+ __ret = INTERNAL_SYSCALL (futex, __err, 6, (futexp), \
+ __lll_private_flag (__op, private), \
+ (val), (timespec), NULL /* Unused. */, \
+ FUTEX_BITSET_MATCH_ANY); \
+ __ret; \
+ })
+
+#define lll_futex_wake(futexp, nr, private) \
+ ({ \
+ long int __ret; \
+ INTERNAL_SYSCALL_DECL (__err); \
+ __ret = INTERNAL_SYSCALL (futex, __err, 4, (futexp), \
+ __lll_private_flag (FUTEX_WAKE, private), \
+ (nr), 0); \
+ __ret; \
+ })
+
+#define lll_robust_dead(futexv, private) \
+ do \
+ { \
+ int *__futexp = &(futexv); \
+ atomic_or (__futexp, FUTEX_OWNER_DIED); \
+ lll_futex_wake (__futexp, 1, private); \
+ } \
+ while (0)
+
+/* Returns non-zero if error happened, zero if success. */
+#define lll_futex_requeue(futexp, nr_wake, nr_move, mutex, val, private) \
+ ({ \
+ long int __ret; \
+ INTERNAL_SYSCALL_DECL (__err); \
+ __ret = INTERNAL_SYSCALL (futex, __err, 6, (futexp), \
+ __lll_private_flag (FUTEX_CMP_REQUEUE, private),\
+ (nr_wake), (nr_move), (mutex), (val)); \
+ INTERNAL_SYSCALL_ERROR_P (__ret, __err); \
+ })
+
+
+/* Returns non-zero if error happened, zero if success. */
+#define lll_futex_wake_unlock(futexp, nr_wake, nr_wake2, futexp2, private) \
+ ({ \
+ long int __ret; \
+ INTERNAL_SYSCALL_DECL (__err); \
+ __ret = INTERNAL_SYSCALL (futex, __err, 6, (futexp), \
+ __lll_private_flag (FUTEX_WAKE_OP, private), \
+ (nr_wake), (nr_wake2), (futexp2), \
+ FUTEX_OP_CLEAR_WAKE_IF_GT_ONE); \
+ INTERNAL_SYSCALL_ERROR_P (__ret, __err); \
+ })
+
+/* Priority Inheritance support. */
+#define lll_futex_wait_requeue_pi(futexp, val, mutex, private) \
+ lll_futex_timed_wait_requeue_pi (futexp, val, NULL, 0, mutex, private)
+
+#define lll_futex_timed_wait_requeue_pi(futexp, val, timespec, clockbit, \
+ mutex, private) \
+ ({ \
+ INTERNAL_SYSCALL_DECL (__err); \
+ int __op = FUTEX_WAIT_REQUEUE_PI | clockbit; \
+ \
+ INTERNAL_SYSCALL (futex, __err, 5, (futexp), \
+ __lll_private_flag (__op, private), \
+ (val), (timespec), mutex); \
+ })
+
+#define lll_futex_cmp_requeue_pi(futexp, nr_wake, nr_move, mutex, val, priv) \
+ ({ \
+ INTERNAL_SYSCALL_DECL (__err); \
+ long int __ret; \
+ \
+ __ret = INTERNAL_SYSCALL (futex, __err, 6, (futexp), \
+ __lll_private_flag (FUTEX_CMP_REQUEUE_PI, priv),\
+ (nr_wake), (nr_move), (mutex), (val)); \
+ INTERNAL_SYSCALL_ERROR_P (__ret, __err); \
+ })
+
+
+#define lll_trylock(lock) \
+ atomic_compare_and_exchange_val_acq(&(lock), 1, 0)
+
+#define lll_cond_trylock(lock) \
+ atomic_compare_and_exchange_val_acq(&(lock), 2, 0)
+
+#define __lll_robust_trylock(futex, id) \
+ (atomic_compare_and_exchange_val_acq (futex, id, 0) != 0)
+#define lll_robust_trylock(lock, id) \
+ __lll_robust_trylock (&(lock), id)
+
+extern void __lll_lock_wait_private (int *futex) attribute_hidden;
+extern void __lll_lock_wait (int *futex, int private) attribute_hidden;
+extern int __lll_robust_lock_wait (int *futex, int private) attribute_hidden;
+
+#define __lll_lock(futex, private) \
+ ((void) ({ \
+ int *__futex = (futex); \
+ if (__builtin_expect (atomic_compare_and_exchange_val_acq (__futex, \
+ 1, 0), 0)) \
+ { \
+ if (__builtin_constant_p (private) && (private) == LLL_PRIVATE) \
+ __lll_lock_wait_private (__futex); \
+ else \
+ __lll_lock_wait (__futex, private); \
+ } \
+ }))
+#define lll_lock(futex, private) __lll_lock (&(futex), private)
+
+
+#define __lll_robust_lock(futex, id, private) \
+ ({ \
+ int *__futex = (futex); \
+ int __val = 0; \
+ \
+ if (__builtin_expect (atomic_compare_and_exchange_bool_acq (__futex, id, \
+ 0), 0)) \
+ __val = __lll_robust_lock_wait (__futex, private); \
+ __val; \
+ })
+#define lll_robust_lock(futex, id, private) \
+ __lll_robust_lock (&(futex), id, private)
+
+
+#define __lll_cond_lock(futex, private) \
+ ((void) ({ \
+ int *__futex = (futex); \
+ if (__builtin_expect (atomic_exchange_acq (__futex, 2), 0)) \
+ __lll_lock_wait (__futex, private); \
+ }))
+#define lll_cond_lock(futex, private) __lll_cond_lock (&(futex), private)
+
+
+#define lll_robust_cond_lock(futex, id, private) \
+ __lll_robust_lock (&(futex), (id) | FUTEX_WAITERS, private)
+
+
+extern int __lll_timedlock_wait (int *futex, const struct timespec *,
+ int private) attribute_hidden;
+extern int __lll_robust_timedlock_wait (int *futex, const struct timespec *,
+ int private) attribute_hidden;
+
+#define __lll_timedlock(futex, abstime, private) \
+ ({ \
+ int *__futex = (futex); \
+ int __val = 0; \
+ \
+ if (__builtin_expect (atomic_exchange_acq (__futex, 1), 0)) \
+ __val = __lll_timedlock_wait (__futex, abstime, private); \
+ __val; \
+ })
+#define lll_timedlock(futex, abstime, private) \
+ __lll_timedlock (&(futex), abstime, private)
+
+
+#define __lll_robust_timedlock(futex, abstime, id, private) \
+ ({ \
+ int *__futex = (futex); \
+ int __val = 0; \
+ \
+ if (__builtin_expect (atomic_compare_and_exchange_bool_acq (__futex, id, \
+ 0), 0)) \
+ __val = __lll_robust_timedlock_wait (__futex, abstime, private); \
+ __val; \
+ })
+#define lll_robust_timedlock(futex, abstime, id, private) \
+ __lll_robust_timedlock (&(futex), abstime, id, private)
+
+
+#define __lll_unlock(futex, private) \
+ (void) \
+ ({ int *__futex = (futex); \
+ int __oldval = atomic_exchange_rel (__futex, 0); \
+ if (__builtin_expect (__oldval > 1, 0)) \
+ lll_futex_wake (__futex, 1, private); \
+ lll_futex_wake (__futex, 1, private); \
+ })
+#define lll_unlock(futex, private) __lll_unlock(&(futex), private)
+
+
+#define __lll_robust_unlock(futex, private) \
+ (void) \
+ ({ int *__futex = (futex); \
+ int __oldval = atomic_exchange_rel (__futex, 0); \
+ if (__builtin_expect (__oldval & FUTEX_WAITERS, 0)) \
+ lll_futex_wake (__futex, 1, private); \
+ lll_futex_wake (__futex, 1, private); \
+ })
+#define lll_robust_unlock(futex, private) \
+ __lll_robust_unlock(&(futex), private)
+
+
+#define lll_islocked(futex) \
+ (futex != 0)
+
+
+/* Our internal lock implementation is identical to the binary-compatible
+ mutex implementation. */
+
+/* Initializers for lock. */
+#define LLL_LOCK_INITIALIZER (0)
+#define LLL_LOCK_INITIALIZER_LOCKED (1)
+
+/* The states of a lock are:
+ 0 - untaken
+ 1 - taken by one user
+ >1 - taken by more users */
+
+/* The kernel notifies a process which uses CLONE_CHILD_CLEARTID via futex
+ wakeup when the clone terminates. The memory location contains the
+ thread ID while the clone is running and is reset to zero
+ afterwards. */
+#define lll_wait_tid(tid) \
+ do { \
+ __typeof (tid) __tid; \
+ while ((__tid = (tid)) != 0) \
+ lll_futex_wait (&(tid), __tid, LLL_SHARED);\
+ } while (0)
+
+extern int __lll_timedwait_tid (int *, const struct timespec *)
+ attribute_hidden;
+
+#define lll_timedwait_tid(tid, abstime) \
+ ({ \
+ int __res = 0; \
+ if ((tid) != 0) \
+ __res = __lll_timedwait_tid (&(tid), (abstime)); \
+ __res; \
+ })
+
+#endif /* lowlevellock.h */
diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/aarch64/pt-raise.c b/libpthread/nptl/sysdeps/unix/sysv/linux/aarch64/pt-raise.c
new file mode 100644
index 000000000..6c0d4b5d3
--- /dev/null
+++ b/libpthread/nptl/sysdeps/unix/sysv/linux/aarch64/pt-raise.c
@@ -0,0 +1,18 @@
+/* Copyright (C) 2002-2013 Free Software Foundation, Inc.
+ Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+ 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 <nptl/sysdeps/unix/sysv/linux/raise.c>
diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/aarch64/pthread_once.c b/libpthread/nptl/sysdeps/unix/sysv/linux/aarch64/pthread_once.c
new file mode 100644
index 000000000..b77939d26
--- /dev/null
+++ b/libpthread/nptl/sysdeps/unix/sysv/linux/aarch64/pthread_once.c
@@ -0,0 +1,90 @@
+/* Copyright (C) 2003-2013 Free Software Foundation, Inc.
+ Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
+
+ 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 "pthreadP.h"
+#include <lowlevellock.h>
+
+unsigned long int __fork_generation attribute_hidden;
+
+static void
+clear_once_control (void *arg)
+{
+ pthread_once_t *once_control = (pthread_once_t *) arg;
+
+ *once_control = 0;
+ lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE);
+}
+
+
+int
+__pthread_once (once_control, init_routine)
+ pthread_once_t *once_control;
+ void (*init_routine) (void);
+{
+ while (1)
+ {
+ int oldval, val, newval;
+
+ val = *once_control;
+ do
+ {
+ /* Check if the initialized has already been done. */
+ if ((val & 2) != 0)
+ return 0;
+
+ oldval = val;
+ newval = (oldval & 3) | __fork_generation | 1;
+ val = atomic_compare_and_exchange_val_acq (once_control, newval,
+ oldval);
+ }
+ while (__builtin_expect (val != oldval, 0));
+
+ /* Check if another thread already runs the initializer. */
+ if ((oldval & 1) != 0)
+ {
+ /* Check whether the initializer execution was interrupted
+ by a fork. */
+ if (((oldval ^ newval) & -4) == 0)
+ {
+ /* Same generation, some other thread was faster. Wait. */
+ lll_futex_wait (once_control, newval, LLL_PRIVATE);
+ continue;
+ }
+ }
+
+ /* This thread is the first here. Do the initialization.
+ Register a cleanup handler so that in case the thread gets
+ interrupted the initialization can be restarted. */
+ pthread_cleanup_push (clear_once_control, once_control);
+
+ init_routine ();
+
+ pthread_cleanup_pop (0);
+
+
+ /* Add one to *once_control. */
+ atomic_increment (once_control);
+
+ /* Wake up all other threads. */
+ lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE);
+ break;
+ }
+
+ return 0;
+}
+weak_alias (__pthread_once, pthread_once)
+strong_alias (__pthread_once, __pthread_once_internal)
diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/aarch64/sysdep-cancel.h b/libpthread/nptl/sysdeps/unix/sysv/linux/aarch64/sysdep-cancel.h
new file mode 100644
index 000000000..0942e819e
--- /dev/null
+++ b/libpthread/nptl/sysdeps/unix/sysv/linux/aarch64/sysdep-cancel.h
@@ -0,0 +1,132 @@
+/* Copyright (C) 2003-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 <sysdep.h>
+#include <tls.h>
+#ifndef __ASSEMBLER__
+# include <pthreadP.h>
+#endif
+
+#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt
+
+# undef PSEUDO
+# define PSEUDO(name, syscall_name, args) \
+ .section ".text"; \
+ENTRY (__##syscall_name##_nocancel); \
+.Lpseudo_nocancel: \
+ DO_CALL (syscall_name, args); \
+.Lpseudo_finish: \
+ cmn x0, 4095; \
+ b.cs .Lsyscall_error; \
+ .subsection 2; \
+ .size __##syscall_name##_nocancel,.-__##syscall_name##_nocancel; \
+ENTRY (name); \
+ SINGLE_THREAD_P(16); \
+ cbz w16, .Lpseudo_nocancel; \
+ /* Setup common stack frame no matter the number of args. \
+ Also save the first arg, since it's basically free. */ \
+ stp x30, x0, [sp, -64]!; \
+ cfi_adjust_cfa_offset (64); \
+ cfi_rel_offset (x30, 0); \
+ DOCARGS_##args; /* save syscall args around CENABLE. */ \
+ CENABLE; \
+ mov x16, x0; /* save mask around syscall. */ \
+ UNDOCARGS_##args; /* restore syscall args. */ \
+ DO_CALL (syscall_name, args); \
+ str x0, [sp, 8]; /* save result around CDISABLE. */ \
+ mov x0, x16; /* restore mask for CDISABLE. */ \
+ CDISABLE; \
+ /* Break down the stack frame, restoring result at once. */ \
+ ldp x30, x0, [sp], 64; \
+ cfi_adjust_cfa_offset (-64); \
+ cfi_restore (x30); \
+ b .Lpseudo_finish; \
+ cfi_endproc; \
+ .size name, .-name; \
+ .previous
+
+# undef PSEUDO_END
+# define PSEUDO_END(name) \
+ SYSCALL_ERROR_HANDLER; \
+ cfi_endproc
+
+# define DOCARGS_0
+# define DOCARGS_1
+# define DOCARGS_2 str x1, [sp, 16]
+# define DOCARGS_3 stp x1, x2, [sp, 16]
+# define DOCARGS_4 DOCARGS_3; str x3, [sp, 32]
+# define DOCARGS_5 DOCARGS_3; stp x3, x4, [sp, 32]
+# define DOCARGS_6 DOCARGS_5; str x5, [sp, 48]
+
+# define UNDOCARGS_0
+# define UNDOCARGS_1 ldr x0, [sp, 8]
+# define UNDOCARGS_2 ldp x0, x1, [sp, 8]
+# define UNDOCARGS_3 UNDOCARGS_1; ldp x1, x2, [sp, 16]
+# define UNDOCARGS_4 UNDOCARGS_2; ldp x2, x3, [sp, 24]
+# define UNDOCARGS_5 UNDOCARGS_3; ldp x3, x4, [sp, 32]
+# define UNDOCARGS_6 UNDOCARGS_4; ldp x4, x5, [sp, 40]
+
+# if defined IS_IN_libpthread
+# define CENABLE bl __pthread_enable_asynccancel
+# define CDISABLE bl __pthread_disable_asynccancel
+# define __local_multiple_threads __pthread_multiple_threads
+# elif !defined NOT_IN_libc
+# define CENABLE bl __libc_enable_asynccancel
+# define CDISABLE bl __libc_disable_asynccancel
+# define __local_multiple_threads __libc_multiple_threads
+# elif defined IS_IN_librt
+# define CENABLE bl __librt_enable_asynccancel
+# define CDISABLE bl __librt_disable_asynccancel
+# else
+# error Unsupported library
+# endif
+
+# if defined IS_IN_libpthread || !defined NOT_IN_libc
+# ifndef __ASSEMBLER__
+extern int __local_multiple_threads attribute_hidden;
+# define SINGLE_THREAD_P __builtin_expect (__local_multiple_threads == 0, 1)
+# else
+# define SINGLE_THREAD_P(R) \
+ adrp x##R, __local_multiple_threads; \
+ ldr w##R, [x##R, :lo12:__local_multiple_threads]
+# endif
+# else
+/* There is no __local_multiple_threads for librt, so use the TCB. */
+# ifndef __ASSEMBLER__
+# define SINGLE_THREAD_P \
+ __builtin_expect (THREAD_GETMEM (THREAD_SELF, \
+ header.multiple_threads) == 0, 1)
+# else
+# define SINGLE_THREAD_P(R) \
+ mrs x##R, tpidr_el0; \
+ sub x##R, x##R, PTHREAD_SIZEOF; \
+ ldr w##R, [x##R, PTHREAD_MULTIPLE_THREADS_OFFSET]
+# endif
+# endif
+
+#elif !defined __ASSEMBLER__
+
+/* For rtld, et cetera. */
+# define SINGLE_THREAD_P 1
+# define NO_CANCELLATION 1
+
+#endif
+
+#ifndef __ASSEMBLER__
+# define RTLD_SINGLE_THREAD_P \
+ __builtin_expect (THREAD_GETMEM (THREAD_SELF, \
+ header.multiple_threads) == 0, 1)
+#endif
diff --git a/utils/ldd.c b/utils/ldd.c
index e7430fca5..37a069b4f 100644
--- a/utils/ldd.c
+++ b/utils/ldd.c
@@ -15,6 +15,11 @@
#include "porting.h"
+#if defined(__aarch64__)
+#define MATCH_MACHINE(x) (x == EM_AARCH64)
+#define ELFCLASSM ELFCLASS64
+#endif
+
#if defined(__alpha__)
#define MATCH_MACHINE(x) (x == EM_ALPHA)
#define ELFCLASSM ELFCLASS64