/*
* Copyright (c) 1997 Mark Brinicombe
- * Copyright (c) 2010 Android Open Source Project.
+ * Copyright (C) 2010 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
// According to the ARM AAPCS document, we only need to save
// the following registers:
//
-// Core r4-r14
-//
-// VFP d8-d15 (see section 5.1.2.1)
+// Core r4-r11, sp, lr
+// AAPCS 5.1.1:
+// A subroutine must preserve the contents of the registers r4-r8, r10, r11
+// and SP (and r9 in PCS variants that designate r9 as v6).
//
+// VFP d8-d15
+// AAPCS 5.1.2.1:
// Registers s16-s31 (d8-d15, q4-q7) must be preserved across subroutine
// calls; registers s0-s15 (d0-d7, q0-q3) do not need to be preserved
// (and can be used for passing arguments or returning results in standard
// FPSCR saved because glibc does.
// The internal structure of a jmp_buf is totally private.
-// Current layout (may change in the future):
+// Current layout (changes from release to release):
//
-// word name description
-// 0 magic magic number
-// 1 sigmask signal mask (not used with _setjmp / _longjmp)
-// 2 float_base base of float registers (d8 to d15)
-// 18 float_state floating-point status and control register
-// 19 core_base base of core registers (r4 to r14)
-// 30 reserved reserved entries (room to grow)
+// word name description
+// 0 sigflag/cookie setjmp cookie in top 31 bits, signal mask flag in low bit
+// 1 sigmask signal mask (not used with _setjmp / _longjmp)
+// 2 float_base base of float registers (d8 to d15)
+// 18 float_state floating-point status and control register
+// 19 core_base base of core registers (r4-r11, r13-r14)
+// 29 checksum checksum of all of the core registers, to give better error messages.
+// 30 reserved reserved entries (room to grow)
// 64
//
// NOTE: float_base must be at an even word index, since the
#define _JB_FLOAT_BASE (_JB_SIGMASK+1)
#define _JB_FLOAT_STATE (_JB_FLOAT_BASE + (15-8+1)*2)
#define _JB_CORE_BASE (_JB_FLOAT_STATE+1)
+#define _JB_CHECKSUM (_JB_CORE_BASE+10)
ENTRY(setjmp)
mov r1, #1
b sigsetjmp
END(_setjmp)
+#define MANGLE_REGISTERS 1
+#define USE_CHECKSUM 1
+
+.macro m_mangle_registers reg
+#if MANGLE_REGISTERS
+ eor r4, r4, \reg
+ eor r5, r5, \reg
+ eor r6, r6, \reg
+ eor r7, r7, \reg
+ eor r8, r8, \reg
+ eor r9, r9, \reg
+ eor r10, r10, \reg
+ eor r11, r11, \reg
+ eor r13, r13, \reg
+ eor r14, r14, \reg
+#endif
+.endm
+
+.macro m_unmangle_registers reg
+ m_mangle_registers \reg
+.endm
+
+.macro m_calculate_checksum dst, src, scratch
+ mov \dst, #0
+ .irp i,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28
+ ldr \scratch, [\src, #(\i * 4)]
+ eor \dst, \dst, \scratch
+ .endr
+.endm
+
// int sigsetjmp(sigjmp_buf env, int save_signal_mask);
ENTRY(sigsetjmp)
- // Record whether or not we're saving the signal mask.
+ stmfd sp!, {r0, lr}
+ .cfi_def_cfa_offset 8
+ .cfi_rel_offset r0, 0
+ .cfi_rel_offset lr, 4
+
+ mov r0, r1
+ bl __bionic_setjmp_cookie_get
+ mov r1, r0
+
+ ldmfd sp, {r0}
+
+ // Save the setjmp cookie for later.
+ bic r2, r1, #1
+ stmfd sp!, {r2}
+ .cfi_adjust_cfa_offset 4
+
+ // Record the setjmp cookie and whether or not we're saving the signal mask.
str r1, [r0, #(_JB_SIGFLAG * 4)]
// Do we need to save the signal mask?
- teq r1, #0
+ tst r1, #1
beq 1f
- // Get current signal mask.
- stmfd sp!, {r0, r14}
- .cfi_def_cfa_offset 8
- .cfi_rel_offset r0, 0
- .cfi_rel_offset r14, 4
- mov r0, #0
- bl sigblock
- mov r1, r0
- ldmfd sp!, {r0, r14}
- .cfi_def_cfa_offset 0
+ // Align the stack.
+ sub sp, #4
+ .cfi_adjust_cfa_offset 4
- // Save the signal mask.
- str r1, [r0, #(_JB_SIGMASK * 4)]
+ // Save the current signal mask.
+ add r2, r0, #(_JB_SIGMASK * 4)
+ mov r0, #2 // SIG_SETMASK
+ mov r1, #0
+ bl sigprocmask
+
+ // Unalign the stack.
+ add sp, #4
+ .cfi_adjust_cfa_offset -4
1:
+ ldmfd sp!, {r2}
+ .cfi_adjust_cfa_offset -4
+ ldmfd sp!, {r0, lr}
+ .cfi_adjust_cfa_offset -8
+ .cfi_restore r0
+ .cfi_restore lr
+
// Save core registers.
add r1, r0, #(_JB_CORE_BASE * 4)
- stmia r1, {r4-r14}
+ m_mangle_registers r2
+
+ // ARM deprecates using sp in the register list for stmia.
+ stmia r1, {r4-r11, lr}
+ str sp, [r1, #(9 * 4)]
+ m_unmangle_registers r2
// Save floating-point registers.
add r1, r0, #(_JB_FLOAT_BASE * 4)
fmrx r1, fpscr
str r1, [r0, #(_JB_FLOAT_STATE * 4)]
+#if USE_CHECKSUM
+ // Calculate the checksum.
+ m_calculate_checksum r12, r0, r2
+ str r12, [r0, #(_JB_CHECKSUM * 4)]
+#endif
+
mov r0, #0
bx lr
END(sigsetjmp)
// void siglongjmp(sigjmp_buf env, int value);
ENTRY(siglongjmp)
- // Do we need to restore the signal mask?
- ldr r2, [r0, #(_JB_SIGFLAG * 4)]
- teq r2, #0
- beq 1f
-
- // Restore the signal mask.
- stmfd sp!, {r0, r1, r14}
+ stmfd sp!, {r0, r1, lr}
.cfi_def_cfa_offset 12
.cfi_rel_offset r0, 0
.cfi_rel_offset r1, 4
- .cfi_rel_offset r14, 8
- sub sp, sp, #4 // Align the stack.
- .cfi_adjust_cfa_offset 4
+ .cfi_rel_offset lr, 8
+
+#if USE_CHECKSUM
+ // Check the checksum before doing anything.
+ m_calculate_checksum r12, r0, r3
+ ldr r2, [r0, #(_JB_CHECKSUM * 4)]
+
+ teq r2, r12
+ bne __bionic_setjmp_checksum_mismatch
+#endif
+
+ // Fetch the signal flag.
+ ldr r1, [r0, #(_JB_SIGFLAG * 4)]
+ // Do we need to restore the signal mask?
+ ands r1, r1, #1
+ beq 1f
+
+ // Restore the signal mask.
ldr r0, [r0, #(_JB_SIGMASK * 4)]
bl sigsetmask
- add sp, sp, #4 // Unalign the stack.
- .cfi_adjust_cfa_offset -4
- ldmfd sp!, {r0, r1, r14}
- .cfi_def_cfa_offset 0
-
1:
+ ldmfd sp!, {r0, r1, lr}
+ .cfi_adjust_cfa_offset -12
+ .cfi_restore r0
+ .cfi_restore r1
+ .cfi_restore lr
+
// Restore floating-point registers.
add r2, r0, #(_JB_FLOAT_BASE * 4)
vldmia r2, {d8-d15}
ldr r2, [r0, #(_JB_FLOAT_STATE * 4)]
fmxr fpscr, r2
+ // Load the cookie.
+ ldr r3, [r0, #(_JB_SIGFLAG * 4)]
+ bic r3, r3, #1
+
// Restore core registers.
add r2, r0, #(_JB_CORE_BASE * 4)
- ldmia r2, {r4-r14}
- // Validate sp and r14.
- teq sp, #0
- teqne r14, #0
- bleq longjmperror
+ // ARM deprecates using sp in the register list for ldmia.
+ ldmia r2, {r4-r11, lr}
+ ldr sp, [r2, #(9 * 4)]
+ m_unmangle_registers r3
+
+ // Save the return value/address and check the setjmp cookie.
+ stmfd sp!, {r1, lr}
+ .cfi_adjust_cfa_offset 8
+ .cfi_rel_offset lr, 4
+ mov r0, r3
+ bl __bionic_setjmp_cookie_check
+
+ // Restore return value/address.
+ ldmfd sp!, {r0, lr}
+ .cfi_adjust_cfa_offset -8
+ .cfi_restore lr
- // Set return value.
- mov r0, r1
teq r0, #0
moveq r0, #1
bx lr