Merge "riscv64 setjmp."
This commit is contained in:
commit
b15a64f722
4 changed files with 299 additions and 5 deletions
|
@ -924,6 +924,7 @@ cc_library_static {
|
||||||
srcs: [
|
srcs: [
|
||||||
"arch-riscv64/bionic/__bionic_clone.S",
|
"arch-riscv64/bionic/__bionic_clone.S",
|
||||||
"arch-riscv64/bionic/_exit_with_stack_teardown.S",
|
"arch-riscv64/bionic/_exit_with_stack_teardown.S",
|
||||||
|
"arch-riscv64/bionic/setjmp.S",
|
||||||
"arch-riscv64/bionic/syscall.S",
|
"arch-riscv64/bionic/syscall.S",
|
||||||
"arch-riscv64/bionic/vfork.S",
|
"arch-riscv64/bionic/vfork.S",
|
||||||
],
|
],
|
||||||
|
|
289
libc/arch-riscv64/bionic/setjmp.S
Normal file
289
libc/arch-riscv64/bionic/setjmp.S
Normal file
|
@ -0,0 +1,289 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2013 The Android Open Source Project
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in
|
||||||
|
* the documentation and/or other materials provided with the
|
||||||
|
* distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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
|
||||||
|
* COPYRIGHT OWNER OR 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <private/bionic_asm.h>
|
||||||
|
#include <private/bionic_constants.h>
|
||||||
|
|
||||||
|
// The internal structure of a jmp_buf is totally private.
|
||||||
|
// Current layout (changes from release to release):
|
||||||
|
//
|
||||||
|
// word name description
|
||||||
|
// 0 sigflag/cookie setjmp cookie in top 31 bits, signal mask flag in low bit
|
||||||
|
// 1 sigmask 64-bit signal mask
|
||||||
|
// 2 ra
|
||||||
|
// 3 s0
|
||||||
|
// ......
|
||||||
|
// 14 s11
|
||||||
|
// 15 sp
|
||||||
|
// 16 fs0
|
||||||
|
// ......
|
||||||
|
// 27 fs11
|
||||||
|
// 28 checksum
|
||||||
|
// _JBLEN: defined in bionic/libc/include/setjmp.h
|
||||||
|
|
||||||
|
#define _JB_SIGFLAG 0
|
||||||
|
#define _JB_SIGMASK 1 * 8
|
||||||
|
#define _JB_RA 2 * 8
|
||||||
|
#define _JB_S0 3 * 8
|
||||||
|
#define _JB_S1 4 * 8
|
||||||
|
#define _JB_S2 5 * 8
|
||||||
|
#define _JB_S3 6 * 8
|
||||||
|
#define _JB_S4 7 * 8
|
||||||
|
#define _JB_S5 8 * 8
|
||||||
|
#define _JB_S6 9 * 8
|
||||||
|
#define _JB_S7 10 * 8
|
||||||
|
#define _JB_S8 11 * 8
|
||||||
|
#define _JB_S9 12 * 8
|
||||||
|
#define _JB_S10 13 * 8
|
||||||
|
#define _JB_S11 14 * 8
|
||||||
|
#define _JB_SP 15 * 8
|
||||||
|
#define _JB_FS0 16 * 8
|
||||||
|
#define _JB_FS1 17 * 8
|
||||||
|
#define _JB_FS2 18 * 8
|
||||||
|
#define _JB_FS3 19 * 8
|
||||||
|
#define _JB_FS4 20 * 8
|
||||||
|
#define _JB_FS5 21 * 8
|
||||||
|
#define _JB_FS6 22 * 8
|
||||||
|
#define _JB_FS7 23 * 8
|
||||||
|
#define _JB_FS8 24 * 8
|
||||||
|
#define _JB_FS9 25 * 8
|
||||||
|
#define _JB_FS10 26 * 8
|
||||||
|
#define _JB_FS11 27 * 8
|
||||||
|
#define _JB_CHECKSUM 28 * 8
|
||||||
|
|
||||||
|
.macro m_mangle_registers reg, sp_reg
|
||||||
|
xor s0, s0, \reg
|
||||||
|
xor s1, s1, \reg
|
||||||
|
xor s2, s2, \reg
|
||||||
|
xor s3, s3, \reg
|
||||||
|
xor s4, s4, \reg
|
||||||
|
xor s5, s5, \reg
|
||||||
|
xor s6, s6, \reg
|
||||||
|
xor s7, s7, \reg
|
||||||
|
xor s8, s8, \reg
|
||||||
|
xor s9, s9, \reg
|
||||||
|
xor s10, s10, \reg
|
||||||
|
xor s11, s11, \reg
|
||||||
|
xor \sp_reg, \sp_reg, \reg
|
||||||
|
.endm
|
||||||
|
|
||||||
|
.macro m_calculate_checksum dst, src, scratch
|
||||||
|
li \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
|
||||||
|
ld \scratch, (\i * 8)(\src)
|
||||||
|
xor \dst, \dst, \scratch
|
||||||
|
.endr
|
||||||
|
.endm
|
||||||
|
|
||||||
|
.macro m_unmangle_registers reg, sp_reg
|
||||||
|
m_mangle_registers \reg, sp_reg=\sp_reg
|
||||||
|
.endm
|
||||||
|
|
||||||
|
ENTRY(setjmp)
|
||||||
|
__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(setjmp)
|
||||||
|
li a1, 1
|
||||||
|
tail PIC_PLT(sigsetjmp)
|
||||||
|
END(setjmp)
|
||||||
|
|
||||||
|
ENTRY(_setjmp)
|
||||||
|
__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(_setjmp)
|
||||||
|
li a1, 0
|
||||||
|
tail PIC_PLT(sigsetjmp)
|
||||||
|
END(_setjmp)
|
||||||
|
|
||||||
|
// int sigsetjmp(sigjmp_buf env, int save_signal_mask);
|
||||||
|
ENTRY(sigsetjmp)
|
||||||
|
__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(sigsetjmp)
|
||||||
|
addi sp, sp, -24
|
||||||
|
sd a0, 0(sp)
|
||||||
|
sd a1, 8(sp)
|
||||||
|
sd ra, 16(sp)
|
||||||
|
|
||||||
|
// Get the cookie and store it along with the signal flag.
|
||||||
|
mv a0, a1
|
||||||
|
call PIC_PLT(__bionic_setjmp_cookie_get)
|
||||||
|
mv a1, a0
|
||||||
|
ld a0, 0(sp)
|
||||||
|
sd a1, _JB_SIGFLAG(a0)
|
||||||
|
|
||||||
|
// Do we need to save the signal mask?
|
||||||
|
andi a1, a1, 1
|
||||||
|
beqz a1, 1f
|
||||||
|
|
||||||
|
// Save current signal mask.
|
||||||
|
// The 'how'/a0 argument is ignored if set is NULL.
|
||||||
|
li a1, 0 // NULL
|
||||||
|
addi a2, a0, _JB_SIGMASK // old_mask.
|
||||||
|
call PIC_PLT(sigprocmask)
|
||||||
|
|
||||||
|
ld a1, 8(sp)
|
||||||
|
|
||||||
|
1:
|
||||||
|
// Restore original a0/a1/ra.
|
||||||
|
ld a0, 0(sp)
|
||||||
|
ld a1, 8(sp)
|
||||||
|
ld ra, 16(sp)
|
||||||
|
addi sp, sp, 24
|
||||||
|
|
||||||
|
// Mask off the signal flag bit.
|
||||||
|
andi a1, a1, -2
|
||||||
|
|
||||||
|
// Save core registers.
|
||||||
|
mv a2, sp
|
||||||
|
m_mangle_registers a1, sp_reg=a2
|
||||||
|
sd ra, _JB_RA(a0)
|
||||||
|
sd s0, _JB_S0(a0)
|
||||||
|
sd s1, _JB_S1(a0)
|
||||||
|
sd s2, _JB_S2(a0)
|
||||||
|
sd s3, _JB_S3(a0)
|
||||||
|
sd s4, _JB_S4(a0)
|
||||||
|
sd s5, _JB_S5(a0)
|
||||||
|
sd s6, _JB_S6(a0)
|
||||||
|
sd s7, _JB_S7(a0)
|
||||||
|
sd s8, _JB_S8(a0)
|
||||||
|
sd s9, _JB_S9(a0)
|
||||||
|
sd s10, _JB_S10(a0)
|
||||||
|
sd s11, _JB_S11(a0)
|
||||||
|
sd sp, _JB_SP(a0)
|
||||||
|
m_unmangle_registers a1, sp_reg=a2
|
||||||
|
|
||||||
|
// Save floating point registers.
|
||||||
|
fsd fs0, _JB_FS0(a0)
|
||||||
|
fsd fs1, _JB_FS1(a0)
|
||||||
|
fsd fs2, _JB_FS2(a0)
|
||||||
|
fsd fs3, _JB_FS3(a0)
|
||||||
|
fsd fs4, _JB_FS4(a0)
|
||||||
|
fsd fs5, _JB_FS5(a0)
|
||||||
|
fsd fs6, _JB_FS6(a0)
|
||||||
|
fsd fs7, _JB_FS7(a0)
|
||||||
|
fsd fs8, _JB_FS8(a0)
|
||||||
|
fsd fs9, _JB_FS9(a0)
|
||||||
|
fsd fs10, _JB_FS10(a0)
|
||||||
|
fsd fs11, _JB_FS11(a0)
|
||||||
|
|
||||||
|
// Calculate the checksum and save it.
|
||||||
|
m_calculate_checksum t0, a0, t1
|
||||||
|
sd t0, _JB_CHECKSUM(a0)
|
||||||
|
|
||||||
|
li a0, 0
|
||||||
|
ret
|
||||||
|
END(sigsetjmp)
|
||||||
|
|
||||||
|
// void siglongjmp(sigjmp_buf env, int value);
|
||||||
|
ENTRY(siglongjmp)
|
||||||
|
__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(siglongjmp)
|
||||||
|
// Check the checksum before doing anything.
|
||||||
|
m_calculate_checksum t0, a0, t1
|
||||||
|
ld t1, _JB_CHECKSUM(a0)
|
||||||
|
bne t0, t1, 3f
|
||||||
|
|
||||||
|
// Do we need to restore the signal mask?
|
||||||
|
ld a2, _JB_SIGFLAG(a0)
|
||||||
|
andi a3, a2, 1
|
||||||
|
beqz a3, 1f
|
||||||
|
|
||||||
|
addi sp, sp, -16
|
||||||
|
sd a0, 0(sp)
|
||||||
|
sd ra, 8(sp)
|
||||||
|
|
||||||
|
// Restore the signal mask.
|
||||||
|
mv t0, a1 // Save 'value'.
|
||||||
|
|
||||||
|
mv a2, a0
|
||||||
|
li a0, 2 // SIG_SETMASK
|
||||||
|
addi a1, a2, _JB_SIGMASK // new_mask
|
||||||
|
li a2, 0 // NULL
|
||||||
|
call PIC_PLT(sigprocmask)
|
||||||
|
mv a1, t0 // Restore 'value'.
|
||||||
|
|
||||||
|
// Restore original a0 and ra.
|
||||||
|
ld a0, 0(sp)
|
||||||
|
ld ra, 8(sp)
|
||||||
|
addi sp, sp, 16
|
||||||
|
|
||||||
|
ld a2, _JB_SIGFLAG(a0)
|
||||||
|
1:
|
||||||
|
// Restore core registers.
|
||||||
|
andi a2, a2, -2
|
||||||
|
ld ra, _JB_RA(a0)
|
||||||
|
ld s0, _JB_S0(a0)
|
||||||
|
ld s1, _JB_S1(a0)
|
||||||
|
ld s2, _JB_S2(a0)
|
||||||
|
ld s3, _JB_S3(a0)
|
||||||
|
ld s4, _JB_S4(a0)
|
||||||
|
ld s5, _JB_S5(a0)
|
||||||
|
ld s6, _JB_S6(a0)
|
||||||
|
ld s7, _JB_S7(a0)
|
||||||
|
ld s8, _JB_S8(a0)
|
||||||
|
ld s9, _JB_S9(a0)
|
||||||
|
ld s10, _JB_S10(a0)
|
||||||
|
ld s11, _JB_S11(a0)
|
||||||
|
ld a3, _JB_SP(a0)
|
||||||
|
m_unmangle_registers a2, sp_reg=a3
|
||||||
|
mv sp, a3
|
||||||
|
|
||||||
|
addi sp, sp, -24
|
||||||
|
sd ra, 0(sp)
|
||||||
|
sd a0, 8(sp)
|
||||||
|
sd a1, 16(sp)
|
||||||
|
ld a0, _JB_SIGFLAG(a0)
|
||||||
|
call PIC_PLT(__bionic_setjmp_cookie_check)
|
||||||
|
ld ra, 0(sp)
|
||||||
|
ld a0, 8(sp)
|
||||||
|
ld a1, 16(sp)
|
||||||
|
addi sp, sp, 24
|
||||||
|
|
||||||
|
// Restore floating point registers.
|
||||||
|
fld fs0, _JB_FS0(a0)
|
||||||
|
fld fs1, _JB_FS1(a0)
|
||||||
|
fld fs2, _JB_FS2(a0)
|
||||||
|
fld fs3, _JB_FS3(a0)
|
||||||
|
fld fs4, _JB_FS4(a0)
|
||||||
|
fld fs5, _JB_FS5(a0)
|
||||||
|
fld fs6, _JB_FS6(a0)
|
||||||
|
fld fs7, _JB_FS7(a0)
|
||||||
|
fld fs8, _JB_FS8(a0)
|
||||||
|
fld fs9, _JB_FS9(a0)
|
||||||
|
fld fs10, _JB_FS10(a0)
|
||||||
|
fld fs11, _JB_FS11(a0)
|
||||||
|
|
||||||
|
// Set return value.
|
||||||
|
beqz a1, 2f
|
||||||
|
li a0, 1
|
||||||
|
2:
|
||||||
|
mv a0, a1
|
||||||
|
ret
|
||||||
|
|
||||||
|
3:
|
||||||
|
call PIC_PLT(__bionic_setjmp_checksum_mismatch)
|
||||||
|
END(siglongjmp)
|
||||||
|
|
||||||
|
ALIAS_SYMBOL(longjmp, siglongjmp)
|
||||||
|
__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(longjmp)
|
||||||
|
ALIAS_SYMBOL(_longjmp, siglongjmp)
|
||||||
|
__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(_longjmp)
|
|
@ -52,6 +52,8 @@
|
||||||
#define _JBLEN 64
|
#define _JBLEN 64
|
||||||
#elif defined(__i386__)
|
#elif defined(__i386__)
|
||||||
#define _JBLEN 10
|
#define _JBLEN 10
|
||||||
|
#elif defined(__riscv)
|
||||||
|
#define _JBLEN 29
|
||||||
#elif defined(__x86_64__)
|
#elif defined(__x86_64__)
|
||||||
#define _JBLEN 11
|
#define _JBLEN 11
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -224,13 +224,15 @@ TEST(setjmp, setjmp_fp_registers) {
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(__arm__)
|
#if defined(__arm__)
|
||||||
#define __JB_SIGFLAG 0
|
#define JB_SIGFLAG_OFFSET 0
|
||||||
#elif defined(__aarch64__)
|
#elif defined(__aarch64__)
|
||||||
#define __JB_SIGFLAG 0
|
#define JB_SIGFLAG_OFFSET 0
|
||||||
#elif defined(__i386__)
|
#elif defined(__i386__)
|
||||||
#define __JB_SIGFLAG 8
|
#define JB_SIGFLAG_OFFSET 8
|
||||||
|
#elif defined(__riscv)
|
||||||
|
#define JB_SIGFLAG_OFFSET 0
|
||||||
#elif defined(__x86_64)
|
#elif defined(__x86_64)
|
||||||
#define __JB_SIGFLAG 8
|
#define JB_SIGFLAG_OFFSET 8
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
TEST_F(setjmp_DeathTest, setjmp_cookie) {
|
TEST_F(setjmp_DeathTest, setjmp_cookie) {
|
||||||
|
@ -238,7 +240,7 @@ TEST_F(setjmp_DeathTest, setjmp_cookie) {
|
||||||
int value = setjmp(jb);
|
int value = setjmp(jb);
|
||||||
ASSERT_EQ(0, value);
|
ASSERT_EQ(0, value);
|
||||||
|
|
||||||
long* sigflag = reinterpret_cast<long*>(jb) + __JB_SIGFLAG;
|
long* sigflag = reinterpret_cast<long*>(jb) + JB_SIGFLAG_OFFSET;
|
||||||
|
|
||||||
// Make sure there's actually a cookie.
|
// Make sure there's actually a cookie.
|
||||||
EXPECT_NE(0, *sigflag & ~1);
|
EXPECT_NE(0, *sigflag & ~1);
|
||||||
|
|
Loading…
Reference in a new issue