From 74d889d6116e46e091566e99d85d9e30bd6bec54 Mon Sep 17 00:00:00 2001 From: Lucinda May Phipps Date: Fri, 27 Aug 2021 01:56:41 +0100 Subject: [PATCH] valgrind: update aarch64-setjmp.S --- packages/valgrind/aarch64-setjmp.S | 238 +++++++++++++++++++++++++---- 1 file changed, 205 insertions(+), 33 deletions(-) diff --git a/packages/valgrind/aarch64-setjmp.S b/packages/valgrind/aarch64-setjmp.S index 1c98ed385..d2fafdbe0 100644 --- a/packages/valgrind/aarch64-setjmp.S +++ b/packages/valgrind/aarch64-setjmp.S @@ -26,20 +26,8 @@ * SUCH DAMAGE. */ -#ifdef __aarch64__ - -// Copied and simplified macros from bionic_asm.h. - -#define ENTRY(f) \ - .text; \ - .globl f; \ - .type f, @function; \ - f: \ - .cfi_startproc \ - -#define END(f) \ - .cfi_endproc; \ - .size f, .-f; \ +#include +#include // According to AARCH64 PCS document we need to save the following // registers: @@ -47,7 +35,7 @@ // Core x19 - x30, sp (see section 5.1.1) // VFP d8 - d15 (see section 5.1.2) // -// NOTE: All the registers saved here will have 64 bit values. +// NOTE: All the registers saved here will have 64 bit vales. // AAPCS mandates that the higher part of q registers do not need to // be saved by the callee. // @@ -57,14 +45,14 @@ // 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 core_base base of core registers (x19-x30, sp) -// 15 float_base base of float registers (d8-d15) -// 23 checksum checksum of core registers -// 24 reserved reserved entries (room to grow) +// 2 core_base base of core registers (x18-x30, sp) +// (We only store the low bits of x18 to avoid leaking the +// shadow call stack address into memory.) +// 16 float_base base of float registers (d8-d15) +// 24 checksum checksum of core registers +// 25 reserved reserved entries (room to grow) // 32 -// 'sigmask' and 'checksum' are not used in this simplified version for valgrind. - #define _JB_SIGFLAG 0 #define _JB_SIGMASK (_JB_SIGFLAG + 1) #define _JB_X30_SP (_JB_SIGMASK + 1) @@ -73,23 +61,113 @@ #define _JB_X24_X25 (_JB_X26_X27 + 2) #define _JB_X22_X23 (_JB_X24_X25 + 2) #define _JB_X20_X21 (_JB_X22_X23 + 2) -#define _JB_X19 (_JB_X20_X21 + 2) -#define _JB_D14_D15 (_JB_X19 + 1) +#define _JB_SCS_X19 (_JB_X20_X21 + 2) +#define _JB_D14_D15 (_JB_SCS_X19 + 2) #define _JB_D12_D13 (_JB_D14_D15 + 2) #define _JB_D10_D11 (_JB_D12_D13 + 2) #define _JB_D8_D9 (_JB_D10_D11 + 2) +#define _JB_CHECKSUM (_JB_D8_D9 + 2) + +#define SCS_MASK (SCS_SIZE - 1) + +.macro m_mangle_registers reg, sp_reg + eor x3, x3, \reg + eor x19, x19, \reg + eor x20, x20, \reg + eor x21, x21, \reg + eor x22, x22, \reg + eor x23, x23, \reg + eor x24, x24, \reg + eor x25, x25, \reg + eor x26, x26, \reg + eor x27, x27, \reg + eor x28, x28, \reg + eor x29, x29, \reg + eor x30, x30, \reg + eor \sp_reg, \sp_reg, \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 + ldr \scratch, [\src, #(\i * 8)] + eor \dst, \dst, \scratch + .endr +.endm + +.macro m_unmangle_registers reg, sp_reg + m_mangle_registers \reg, sp_reg=\sp_reg +.endm -// int setjmp(jmp_buf env); ENTRY(setjmp) +__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(setjmp) + mov w1, #1 + b sigsetjmp +END(setjmp) + +ENTRY(_setjmp) +__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(_setjmp) + mov w1, #0 + b sigsetjmp +END(_setjmp) + +// int sigsetjmp(sigjmp_buf env, int save_signal_mask); +ENTRY(sigsetjmp) +__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(sigsetjmp) + paciasp + .cfi_negate_ra_state + stp x0, x30, [sp, #-16]! + .cfi_def_cfa_offset 16 + .cfi_rel_offset x0, 0 + .cfi_rel_offset x30, 8 + + // Get the cookie and store it along with the signal flag. + mov x0, x1 + bl __bionic_setjmp_cookie_get + mov x1, x0 + ldr x0, [sp, #0] + str x1, [x0, #(_JB_SIGFLAG * 8)] + + // Do we need to save the signal mask? + tbz w1, #0, 1f + + // Save the cookie for later. + stp x1, xzr, [sp, #-16]! + .cfi_adjust_cfa_offset 16 + + // Save current signal mask. + // The 'how' argument is ignored if new_mask is NULL. + mov x1, #0 // NULL. + add x2, x0, #(_JB_SIGMASK * 8) // old_mask. + bl sigprocmask + + ldp x1, xzr, [sp], #16 + .cfi_adjust_cfa_offset -16 + +1: + // Restore original x0 and lr. + ldp x0, x30, [sp], #16 + .cfi_adjust_cfa_offset -16 + .cfi_restore x0 + .cfi_restore x30 + + // Mask off the signal flag bit. + bic x1, x1, #1 + + // Mask off the high bits of the shadow call stack pointer. + and x3, x18, #SCS_MASK + // Save core registers. mov x10, sp + m_mangle_registers x1, sp_reg=x10 stp x30, x10, [x0, #(_JB_X30_SP * 8)] stp x28, x29, [x0, #(_JB_X28_X29 * 8)] stp x26, x27, [x0, #(_JB_X26_X27 * 8)] stp x24, x25, [x0, #(_JB_X24_X25 * 8)] stp x22, x23, [x0, #(_JB_X22_X23 * 8)] stp x20, x21, [x0, #(_JB_X20_X21 * 8)] - str x19, [x0, #(_JB_X19 * 8)] + stp x3, x19, [x0, #(_JB_SCS_X19 * 8)] + m_unmangle_registers x1, sp_reg=x10 // Save floating point registers. stp d14, d15, [x0, #(_JB_D14_D15 * 8)] @@ -97,22 +175,109 @@ ENTRY(setjmp) stp d10, d11, [x0, #(_JB_D10_D11 * 8)] stp d8, d9, [x0, #(_JB_D8_D9 * 8)] - mov w0, #0 - ret -END(setjmp) + // Calculate the checksum. + m_calculate_checksum x12, x0, x2 + str x12, [x0, #(_JB_CHECKSUM * 8)] -// void longjmp(jmp_buf env, int value); -ENTRY(longjmp) + mov w0, #0 + autiasp + .cfi_negate_ra_state + 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 x12, x0, x2 + ldr x2, [x0, #(_JB_CHECKSUM * 8)] + cmp x2, x12 + bne __bionic_setjmp_checksum_mismatch + +#if __has_feature(hwaddress_sanitizer) + stp x0, x30, [sp, #-16]! + .cfi_adjust_cfa_offset 16 + .cfi_rel_offset x0, 0 + .cfi_rel_offset x30, 8 + mov x19, x1 // Save 'value'. + + // load and unmangle destination SP + ldr x2, [x0, #(_JB_SIGFLAG * 8)] + bic x2, x2, #1 + ldr x0, [x0, #(_JB_X30_SP * 8 + 8)] + eor x0, x0, x2 + bl __hwasan_handle_longjmp + + mov x1, x19 // Restore 'value'. + // Restore original x0 and lr. + ldp x0, x30, [sp], #16 + .cfi_adjust_cfa_offset -16 + .cfi_restore x0 + .cfi_restore x30 +#endif + + // Do we need to restore the signal mask? + ldr x2, [x0, #(_JB_SIGFLAG * 8)] + tbz w2, #0, 1f + + stp x0, x30, [sp, #-16]! + .cfi_adjust_cfa_offset 16 + .cfi_rel_offset x0, 0 + .cfi_rel_offset x30, 8 + + // Restore signal mask. + mov x19, x1 // Save 'value'. + + mov x2, x0 + mov x0, #2 // SIG_SETMASK + add x1, x2, #(_JB_SIGMASK * 8) // new_mask. + mov x2, #0 // NULL. + bl sigprocmask + mov x1, x19 // Restore 'value'. + + // Restore original x0 and lr. + ldp x0, x30, [sp], #16 + .cfi_adjust_cfa_offset -16 + .cfi_restore x0 + .cfi_restore x30 + + ldr x2, [x0, #(_JB_SIGFLAG * 8)] +1: // Restore core registers. + bic x2, x2, #1 + // x30 was saved with PAC to jmp_buf in sigsetjmp(). ldp x30, x10, [x0, #(_JB_X30_SP * 8)] + .cfi_negate_ra_state ldp x28, x29, [x0, #(_JB_X28_X29 * 8)] ldp x26, x27, [x0, #(_JB_X26_X27 * 8)] ldp x24, x25, [x0, #(_JB_X24_X25 * 8)] ldp x22, x23, [x0, #(_JB_X22_X23 * 8)] ldp x20, x21, [x0, #(_JB_X20_X21 * 8)] - ldr x19, [x0, #(_JB_X19 * 8)] + ldp x3, x19, [x0, #(_JB_SCS_X19 * 8)] + m_unmangle_registers x2, sp_reg=x10 mov sp, x10 + // Restore the low bits of the shadow call stack pointer. + and x18, x18, #~SCS_MASK + orr x18, x3, x18 + + stp x0, x1, [sp, #-16]! + .cfi_adjust_cfa_offset 16 + .cfi_rel_offset x0, 0 + .cfi_rel_offset x1, 8 + stp x30, xzr, [sp, #-16]! + .cfi_adjust_cfa_offset 16 + .cfi_rel_offset x30, 0 + ldr x0, [x0, #(_JB_SIGFLAG * 8)] + bl __bionic_setjmp_cookie_check + ldp x30, xzr, [sp], #16 + .cfi_adjust_cfa_offset -16 + .cfi_restore x30 + ldp x0, x1, [sp], #16 + .cfi_adjust_cfa_offset -16 + .cfi_restore x0 + .cfi_restore x1 + // Restore floating point registers. ldp d14, d15, [x0, #(_JB_D14_D15 * 8)] ldp d12, d13, [x0, #(_JB_D12_D13 * 8)] @@ -122,7 +287,14 @@ ENTRY(longjmp) // Set return value. cmp w1, wzr csinc w0, w1, wzr, ne + autiasp + .cfi_negate_ra_state ret -END(longjmp) +END(siglongjmp) -#endif // __aarch64__ +ALIAS_SYMBOL(longjmp, siglongjmp) +__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(longjmp) +ALIAS_SYMBOL(_longjmp, siglongjmp) +__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(_longjmp) + +NOTE_GNU_PROPERTY()