Merge "riscv64 setjmp."

This commit is contained in:
Treehugger Robot 2022-10-18 04:09:55 +00:00 committed by Gerrit Code Review
commit b15a64f722
4 changed files with 299 additions and 5 deletions

View file

@ -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",
], ],

View 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)

View file

@ -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

View file

@ -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);