about summary refs log tree commit diff
path: root/sysdeps/arm
diff options
context:
space:
mode:
authorRoland McGrath <roland@hack.frob.com>2015-04-17 09:02:19 -0700
committerRoland McGrath <roland@hack.frob.com>2015-04-17 09:02:19 -0700
commitd1e44df1fa5fefd8a083f6c1e909bbcdc97c6438 (patch)
treea76176eca62c0907dd7f135979312c8e55ad06a5 /sysdeps/arm
parentf70925993ada98039250d46c62fb89c168b8f9d6 (diff)
downloadglibc-d1e44df1fa5fefd8a083f6c1e909bbcdc97c6438.tar.gz
glibc-d1e44df1fa5fefd8a083f6c1e909bbcdc97c6438.tar.xz
glibc-d1e44df1fa5fefd8a083f6c1e909bbcdc97c6438.zip
Add arm-nacl port.
Diffstat (limited to 'sysdeps/arm')
-rw-r--r--sysdeps/arm/nacl/Implies2
-rw-r--r--sysdeps/arm/nacl/Makefile33
-rw-r--r--sysdeps/arm/nacl/____longjmp_chk.S47
-rw-r--r--sysdeps/arm/nacl/aeabi_read_tp.S44
-rw-r--r--sysdeps/arm/nacl/arm-features.h43
-rw-r--r--sysdeps/arm/nacl/dl-machine.h53
-rw-r--r--sysdeps/arm/nacl/dl-trampoline.S278
-rw-r--r--sysdeps/arm/nacl/include/bits/setjmp.h38
-rw-r--r--sysdeps/arm/nacl/shlib-versions4
-rw-r--r--sysdeps/arm/nacl/start.c1
-rw-r--r--sysdeps/arm/nacl/sysdep.h69
-rw-r--r--sysdeps/arm/nacl/tls.h2
12 files changed, 614 insertions, 0 deletions
diff --git a/sysdeps/arm/nacl/Implies b/sysdeps/arm/nacl/Implies
new file mode 100644
index 0000000000..2294208dba
--- /dev/null
+++ b/sysdeps/arm/nacl/Implies
@@ -0,0 +1,2 @@
+arm/nptl
+init_array
diff --git a/sysdeps/arm/nacl/Makefile b/sysdeps/arm/nacl/Makefile
new file mode 100644
index 0000000000..c9226595e6
--- /dev/null
+++ b/sysdeps/arm/nacl/Makefile
@@ -0,0 +1,33 @@
+# Makefile fragment for ARM/NaCl configurations.
+
+# Copyright (C) 2015 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/>.
+
+# sysdeps/nacl/Makefile needs this set to the architecture suffix used in
+# the NaCl SDK.
+nacl-sdk-arch = arm
+
+# We don't really support TLSDESC, even though the compiler thinks it does.
+have-arm-tls-desc = no
+
+ifeq ($(subdir),csu)
+sysdep_routines += aeabi_read_tp
+endif
+
+ifeq ($(subdir),elf)
+sysdep-rtld-routines += aeabi_read_tp
+endif
diff --git a/sysdeps/arm/nacl/____longjmp_chk.S b/sysdeps/arm/nacl/____longjmp_chk.S
new file mode 100644
index 0000000000..f950f17d7b
--- /dev/null
+++ b/sysdeps/arm/nacl/____longjmp_chk.S
@@ -0,0 +1,47 @@
+/* longjmp that validates stack addresses.  ARM/NaCl version.
+   Copyright (C) 2015 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>
+
+	.section .rodata.str1.1,"aMS",%progbits,1
+	.type	longjmp_msg,%object
+longjmp_msg:
+	.string "longjmp causes uninitialized stack frame"
+	.size	longjmp_msg, .-longjmp_msg
+
+	.text
+
+/* We don't have sigaltstack and so any longjmp must be to an outer frame.  */
+.macro check_sp reg
+	cmp sp, \reg
+	bls .Lok
+#ifdef PIC
+	movw r0, #:lower16:longjmp_msg-(.LPIC0+8)
+	movt r0, #:upper16:longjmp_msg-(.LPIC0+8)
+.LPIC0:	add r0, r0, pc
+#else
+	movw r0, #:lower16:longjmp_msg
+	movt r0, #:upper16:longjmp_msg
+#endif
+	b HIDDEN_JUMPTARGET(__fortify_fail)
+.Lok:
+.endm
+
+#define CHECK_SP(reg)	check_sp reg
+#define __longjmp	____longjmp_chk
+#include <__longjmp.S>
diff --git a/sysdeps/arm/nacl/aeabi_read_tp.S b/sysdeps/arm/nacl/aeabi_read_tp.S
new file mode 100644
index 0000000000..153e6dbdcb
--- /dev/null
+++ b/sysdeps/arm/nacl/aeabi_read_tp.S
@@ -0,0 +1,44 @@
+/* ARM EABI helper function for reading the thread pointer.  NaCl version.
+   Copyright (C) 2015 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/>.  */
+
+#include <sysdep.h>
+
+/* GCC will emit calls to this routine under -mtp=soft.  */
+
+	.hidden __aeabi_read_tp
+ENTRY (__aeabi_read_tp)
+	ldr	r0, [r9]
+	sfi_bx	lr
+END (__aeabi_read_tp)
diff --git a/sysdeps/arm/nacl/arm-features.h b/sysdeps/arm/nacl/arm-features.h
new file mode 100644
index 0000000000..b00cfdbfa5
--- /dev/null
+++ b/sysdeps/arm/nacl/arm-features.h
@@ -0,0 +1,43 @@
+/* Macros to test for CPU features on ARM.  NaCl version.
+   Copyright (C) 2015 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 _NACL_ARM_FEATURES_H
+#define _NACL_ARM_FEATURES_H 1
+
+#ifdef __SOFTFP__
+# error NaCl should always have VFP enabled
+#endif
+
+/* NaCl does not support iWMMXt at all.  */
+#define ARM_ASSUME_NO_IWMMXT    1
+
+/* NaCl does not allow instructions to target the pc register.  */
+#define ARM_ALWAYS_BX           1
+
+/* Computed branch targets must be bundle-aligned, which is to 16 bytes.  */
+#define ARM_BX_ALIGN_LOG2       4
+
+/* Two-register addressing modes are never allowed.  */
+#define ARM_NO_INDEX_REGISTER   1
+
+/* Only ARM mode code is allowed, never Thumb mode.  */
+#define NO_THUMB
+
+#include_next <arm-features.h>
+
+#endif  /* arm-features.h */
diff --git a/sysdeps/arm/nacl/dl-machine.h b/sysdeps/arm/nacl/dl-machine.h
new file mode 100644
index 0000000000..81f3755b3b
--- /dev/null
+++ b/sysdeps/arm/nacl/dl-machine.h
@@ -0,0 +1,53 @@
+/* Machine-dependent ELF dynamic relocation inline functions.  ARM/NaCl version.
+   Copyright (C) 2015 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 dl_machine_h
+
+/* This is only needed for handling TEXTRELs and NaCl will never
+   support TEXTRELs at all.  */
+#define CLEAR_CACHE(start, end) __builtin_trap ()
+
+#endif
+
+/* The rest is just machine-specific.
+   This #include is outside the #ifndef because the parts of
+   dl-machine.h used only by dynamic-link.h are outside the guard.  */
+#include <sysdeps/arm/dl-machine.h>
+
+#ifdef dl_machine_h
+
+/* Initial entry point code for the dynamic linker.
+   The C function `_dl_start' is the real entry point;
+   its return value is the user program's entry point.  */
+#undef RTLD_START
+#define RTLD_START asm ("\
+.text\n\
+.globl _start\n\
+.type _start, %function\n\
+.p2align 4\n\
+_start:\n\
+	@ r0 has the pointer to the info block (see nacl_startup.h)\n\
+	mov r1, sp              @ Save stack base for __libc_stack_end.\n\
+	push {r0-r3}            @ Push those, maintaining alignment to 16.\n\
+	mov r0, sp              @ Pointer to {info, sp} is argument.\n\
+	sfi_bl _dl_start\n\
+	pop {r1-r4}             @ Restore stack, getting info block into r1.\n\
+	mov lr, #0              @ Return address for noreturn call.\n\
+	b _dl_start_user");
+
+#endif
diff --git a/sysdeps/arm/nacl/dl-trampoline.S b/sysdeps/arm/nacl/dl-trampoline.S
new file mode 100644
index 0000000000..47bc0cac79
--- /dev/null
+++ b/sysdeps/arm/nacl/dl-trampoline.S
@@ -0,0 +1,278 @@
+/* PLT trampolines.  ARM/NaCl version.
+   Copyright (C) 2015 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>
+
+	.syntax unified
+	.text
+
+@ Change &GOT[n+3] into 8*n.  Note relocs are 8 bytes each.
+.macro compute_reloc_arg pltgot, got2
+	sub r1, \pltgot, \got2	@ r1 = &GOT[n+3] - &GOT[2] = 4*(n-1)
+	sub r1, r1, #4		@ r1 = 4*n
+	add r1, r1, r1		@ r1 *= 2 = 8*n
+.endm
+
+	CFI_SECTIONS
+	.globl _dl_runtime_resolve
+	.type _dl_runtime_resolve, %function
+	.p2align 4
+_dl_runtime_resolve:
+	cfi_startproc
+	cfi_adjust_cfa_offset (8)
+
+	@ We get called with:
+	@ 	lr contains the return address from this call
+	@	stack[1] contains &GOT[n+3] (pointer to function)
+	@	stack[0] points to &GOT[2]
+
+	ldr ip, [sp]		@ ip gets &GOT[2]
+
+	@ Save the argument registers and the return address.
+	@ r4 doesn't need to be saved, but it makes the total
+	@ adjustment to sp (including the two words pushed by
+	@ the PLT code) an even eight words, so sp stays aligned.
+	push {r0-r4, lr}
+	cfi_adjust_cfa_offset (24)
+	cfi_rel_offset (r0, 0)
+	cfi_rel_offset (r1, 4)
+	cfi_rel_offset (r2, 8)
+	cfi_rel_offset (r3, 12)
+	cfi_rel_offset (r4, 16)
+	cfi_rel_offset (lr, 20)
+
+	ldr r1, [sp, #28]	@ r1 gets &GOT[n+3]
+
+	@ Get the 'struct link_map *' for the first argument to _dl_fixup.
+	sfi_breg ip, ldr r0, [\B, #-4]
+
+	@ Get the reloc offset for the second argument to _dl_fixup.
+	compute_reloc_arg r1, ip
+
+	@ This does the real work, and returns the real call target.
+	sfi_bl _dl_fixup
+	mov ip, r0
+
+	@ Restore the saved registers.
+	pop {r0-r4, lr}
+	cfi_adjust_cfa_offset (-24)
+	cfi_restore (r0)
+	cfi_restore (r1)
+	cfi_restore (r2)
+	cfi_restore (r3)
+	cfi_restore (r4)
+	cfi_restore (lr)
+
+	@ Now compensate for the two words pushed by the PLT code.
+	sfi_sp add sp, #8
+	cfi_adjust_cfa_offset (-8)
+
+	@ Finally, jump to the newfound call target.
+	sfi_bx ip
+
+	cfi_endproc
+	.size _dl_runtime_resolve, .-_dl_runtime_resolve
+
+#ifndef PROF
+	.globl _dl_runtime_profile
+	.type _dl_runtime_profile, #function
+	.p2align 4
+_dl_runtime_profile:
+	cfi_startproc
+	cfi_adjust_cfa_offset (8)
+
+	@ We get called with:
+	@ 	lr contains the return address from this call
+	@	stack[1] contains &GOT[n+3] (pointer to function)
+	@	stack[0] points to &GOT[2]
+
+	@ Stack layout:
+	@ sp + 204		framesize returned from pltenter
+	@ sp + 12		La_arm_regs
+	@ sp + 4		Saved two arguments to _dl_profile_fixup
+	@ sp + 0		outgoing argument to _dl_profile_fixup
+	@ For now, we only save the general purpose registers.
+# define PLTEXIT_ARGS		4
+# define LA_ARM_REGS		(PLTEXIT_ARGS + 8)
+# define LA_ARM_REGS_SIZE	(4 * (4 + 1 + 1 + 42))
+# define PLTENTER_FRAMESIZE	(LA_ARM_REGS + LA_ARM_REGS_SIZE)
+# define FRAMESIZE		(((PLTENTER_FRAMESIZE + 4) + 15) & -16)
+
+	@ The NaCl ABI requires that sp be aligned to 16 bytes at call
+	@ sites.  Assuming that was met on entry to the PLT, sp is
+	@ now exactly 8 bytes misaligned.
+	sfi_sp sub sp, #(FRAMESIZE - 8)
+	cfi_def_cfa_offset (FRAMESIZE)
+
+	@ Store the argument registers in La_arm_regs.
+	strd r0, r1, [sp, #LA_ARM_REGS]
+	cfi_offset (r0, LA_ARM_REGS + 0)
+	cfi_offset (r1, LA_ARM_REGS + 4)
+	strd r2, r3, [sp, #(LA_ARM_REGS + 8)]
+	cfi_offset (r2, LA_ARM_REGS + 8)
+	cfi_offset (r3, LA_ARM_REGS + 12)
+
+	ldr ip, [sp, #(FRAMESIZE - 8)]		@ ip gets &GOT[2]
+	ldr r3, [sp, #(FRAMESIZE - 4)]		@ r3 gets &GOT[n+3]
+
+	@ Recover the incoming sp and lr and save those in La_arm_regs.
+	add r0, sp, #FRAMESIZE
+	mov r1, lr
+	strd r0, r1, [sp, #(LA_ARM_REGS + 16)]
+	cfi_offset (sp, LA_ARM_REGS + 16)
+	cfi_offset (lr, LA_ARM_REGS + 20)
+
+	@ Get the 'struct link_map *' for the first arg to _dl_profile_fixup.
+	sfi_breg ip, ldr r0, [\B, #-4]
+
+	@ Get the reloc offset for the second argument to _dl_profile_fixup.
+	compute_reloc_arg r3, ip
+
+	@ The third argument is the original return address, still in lr.
+	mov r2, lr
+
+	@ Compute the fourth argument, the La_arm_regs pointer.
+	add r3, sp, #PLTEXIT_ARGS
+
+	@ Compute the fifth argument, the address of the 'framesize'
+	@ out parameter, and store it at the top of the stack.
+	add ip, sp, #PLTENTER_FRAMESIZE
+	str ip, [sp]
+
+	@ Save away the first two arguments, which we will need
+	@ again for _dl_call_pltexit, below.
+	strd r0, r1, [sp, #PLTEXIT_ARGS]
+
+	@ This does the real work, and returns the real call target.
+	sfi_bl _dl_profile_fixup
+
+	@ The address to call is now in r0.
+
+	@ Check whether we're wrapping this function,
+	@ i.e. if the framesize out parameter is >= 0.
+	ldr	ip, [sp, #PLTENTER_FRAMESIZE]
+	cmp	ip, #0
+	bge	1f
+	cfi_remember_state
+
+	@ Save _dl_profile_fixup's return value: the real call target.
+	mov ip, r0
+
+	@ Restore the registers from the La_arm_regs (perhaps as modified
+	@ by audit modules' pltenter functions).
+	add r1, sp, #LA_ARM_REGS
+	sfi_sp sfi_breg r1, ldmia \B, {r0-r3, sp, lr}
+	cfi_def_cfa_offset (0)
+	cfi_restore (r0)
+	cfi_restore (r1)
+	cfi_restore (r2)
+	cfi_restore (r3)
+	cfi_restore (sp)
+	cfi_restore (lr)
+
+	@ Finally, jump to the newfound call target.
+	sfi_bx ip
+
+1:	cfi_restore_state
+	@ The new frame size is in ip.
+
+	@ Save the fp in the stack slot previously used for the fifth
+	@ argument to _dl_profile_fixup.
+	str fp, [sp]
+	cfi_offset (fp, 0)
+
+	@ Save the result of _dl_profile_fixup, the real call target.
+	@ We'll reuse the stack slot just used for the 'framesize'
+	@ out parameter to _dl_profile_fixup.
+	str r0, [sp, #PLTENTER_FRAMESIZE]
+
+	@ Stack layout:
+	@ fp + 264		call target
+	@ fp + 72		La_arm_regs
+	@ fp + 68		Saved two arguments to _dl_profile_fixup
+	@ fp + 64		saved fp
+	@ fp + 0		La_arm_retval
+	@ sp..fp		copied incoming stack space (plus alignment)
+	@ For now, we only save the general purpose registers.
+# define FP_LA_ARM_RETVAL	0
+# define LA_ARM_RETVAL_SIZE	(4 * (4 + 12))
+# define FP_SAVED_FP		LA_ARM_RETVAL_SIZE
+# define FP_PLTEXIT_ARGS	(FP_SAVED_FP + 4)
+# define FP_LA_ARM_REGS		(FP_PLTEXIT_ARGS + 8)
+# define FP_CALL_TARGET		(FP_LA_ARM_REGS + LA_ARM_REGS_SIZE)
+# define FP_FRAMESIZE		(FP_CALL_TARGET + 4)
+
+	sub fp, sp, #(FP_FRAMESIZE - FRAMESIZE)
+	cfi_def_cfa (fp, FP_FRAMESIZE)
+
+	sub r1, fp, ip
+	@ This doesn't need sfi_sp because we just include the
+	@ sandboxing mask along with the alignment mask.
+	bic sp, r1, #0xc000000f
+
+	@ Copy the stack arguments.  The audit modules' pltenter
+	@ function(s) decided how much needs to be copied.
+	@ Load the sp as modified by pltenter functions, rather
+	@ than what we think the incoming sp was (fp + FP_FRAMESIZE).
+	sfi_breg fp, ldr r1, [\B, #(FP_LA_ARM_REGS + 16)]
+	mov r0, sp
+	mov r2, ip
+	sfi_bl memcpy
+
+	@ Load up the arguments from La_arm_regs and call the user's function.
+	sfi_breg fp, ldr ip, [\B, #FP_CALL_TARGET]
+	sfi_breg fp, ldrd r0, r1, [\B, #FP_LA_ARM_REGS]
+	sfi_breg fp, ldrd r2, r3, [\B, #(FP_LA_ARM_REGS + 8)]
+	sfi_blx ip
+
+	@ Stash the return value registers in La_arm_retval.
+	sfi_breg fp, strd r0, r1, [\B, #FP_LA_ARM_RETVAL]
+	sfi_breg fp, strd r2, r3, [\B, #(FP_LA_ARM_RETVAL + 8)]
+
+	@ Call pltexit.  We saved the first two arguments earlier--they
+	@ are the same ones passed to _dl_profile_fixup.  The latter two
+	@ arguments are La_arm_regs and La_arm_retval blocks, respectively.
+	sfi_breg fp, ldrd r0, r1, [\B, #FP_PLTEXIT_ARGS]
+	add r2, fp, #FP_LA_ARM_REGS
+	add r3, fp, #FP_LA_ARM_RETVAL
+	sfi_bl _dl_call_pltexit
+
+	@ Reload the saved return value registers for the caller.
+	sfi_breg fp, ldrd r0, r1, [\B, #FP_LA_ARM_RETVAL]
+	sfi_breg fp, ldrd r2, r3, [\B, #(FP_LA_ARM_RETVAL + 8)]
+
+	@ Unwind the frame.
+	sfi_sp mov sp, fp
+	cfi_def_cfa_register (sp)
+	ldr fp, [sp, #FP_SAVED_FP]
+	cfi_restore (fp)
+	@ Reload the lr and sp values from La_arm_regs, where they
+	@ might have been modified by pltenter functions, rather than
+	@ computing what we think the incoming value was.
+	ldr lr, [sp, #(FP_LA_ARM_REGS + 20)]
+	cfi_restore (lr)
+	sfi_sp ldr sp, [sp, #(FP_LA_ARM_REGS + 16)]
+	cfi_def_cfa_offset (0)
+
+	@ Finally, return to the caller.
+	sfi_bx lr
+
+	cfi_endproc
+	.size _dl_runtime_profile, .-_dl_runtime_profile
+#endif
+	.previous
diff --git a/sysdeps/arm/nacl/include/bits/setjmp.h b/sysdeps/arm/nacl/include/bits/setjmp.h
new file mode 100644
index 0000000000..41830e5c79
--- /dev/null
+++ b/sysdeps/arm/nacl/include/bits/setjmp.h
@@ -0,0 +1,38 @@
+/* Private jmp_buf-related definitions.  NaCl/ARM version.
+   Copyright (C) 2015 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 _INCLUDE_BITS_SETJMP_H
+#define _INCLUDE_BITS_SETJMP_H 1
+
+#ifndef __ASSEMBLER__
+/* Get the public declarations.  */
+# include <sysdeps/arm/bits/setjmp.h>
+#endif
+
+/* Register list for a ldm/stm instruction to load/store
+   the general registers from a __jmp_buf.
+
+   The generic ARM definition includes r9 (v6), which is not
+   permitted under NaCl.  We add r3 even though it's call-clobbered,
+   just to keep the size the same as the generic version.  */
+#define JMP_BUF_REGLIST		{r3, v1-v5, sl, fp}
+
+/* Index of __jmp_buf where the sp register resides.  */
+#define __JMP_BUF_SP		0
+
+#endif  /* include/bits/setjmp.h */
diff --git a/sysdeps/arm/nacl/shlib-versions b/sysdeps/arm/nacl/shlib-versions
new file mode 100644
index 0000000000..9d94784282
--- /dev/null
+++ b/sysdeps/arm/nacl/shlib-versions
@@ -0,0 +1,4 @@
+# Library=version		Earliest symbol set (optional)
+# ---------------		------------------------------
+
+ld=ld-nacl-arm.so.1
diff --git a/sysdeps/arm/nacl/start.c b/sysdeps/arm/nacl/start.c
new file mode 100644
index 0000000000..25f6fd774a
--- /dev/null
+++ b/sysdeps/arm/nacl/start.c
@@ -0,0 +1 @@
+#include <sysdeps/nacl/start.c>
diff --git a/sysdeps/arm/nacl/sysdep.h b/sysdeps/arm/nacl/sysdep.h
new file mode 100644
index 0000000000..951df3215d
--- /dev/null
+++ b/sysdeps/arm/nacl/sysdep.h
@@ -0,0 +1,69 @@
+/* Assembler macros for ARM/NaCl.
+   Copyright (C) 2015 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 _ARM_NACL_SYSDEP_H
+#define _ARM_NACL_SYSDEP_H	1
+
+#ifdef __ASSEMBLER__
+
+# ifndef NO_THUMB
+#  define NO_THUMB
+# endif
+# define ARM_SFI_MACROS		1
+
+/* The compiler driver primes the assembler with a standard set of
+   macros that includes sfi_breg and sfi_sp.  The sfi_pld macro is
+   redundant with sfi_breg, but libc code uses it so as not to run
+   afoul of the assembler's parsing bug in versions prior to 2.23.2.
+   NaCl never uses an assembler that has this bug.  */
+
+.macro sfi_pld basereg, offset=#0
+	sfi_breg \basereg, pld [\basereg, \offset]
+.endm
+
+#endif
+
+#include <sysdeps/arm/sysdep.h>
+
+#ifdef  __ASSEMBLER__
+
+# undef eabi_fnstart
+# define eabi_fnstart
+# undef eabi_fnend
+# define eabi_fnend
+# undef eabi_save
+# define eabi_save(...)
+# undef eabi_cantunwind
+# define eabi_cantunwind
+# undef eabi_pad
+# define eabi_pad(n)
+
+/* NaCl has its own special way of getting the thread pointer.  */
+# undef	GET_TLS
+# define GET_TLS(tmp)		ldr r0, [r9]
+
+/* Rather than macroizing the code any more, we can just define a few
+   mnemonics as macros here.  */
+# define bl			sfi_bl
+# define bx			sfi_bx
+# define blx			sfi_blx
+# define bxeq			sfi_bxeq /* Only condition now in use.  */
+
+#endif  /* __ASSEMBLER__ */
+
+#endif  /* sysdep.h */
diff --git a/sysdeps/arm/nacl/tls.h b/sysdeps/arm/nacl/tls.h
new file mode 100644
index 0000000000..646e7a9d06
--- /dev/null
+++ b/sysdeps/arm/nacl/tls.h
@@ -0,0 +1,2 @@
+#include <sysdeps/arm/nptl/tls.h>
+#include <sysdeps/nacl/tls.h>