mirror of
https://github.com/ruby/ruby.git
synced 2026-10-28 16:36:20 +08:00
158 lines
3.6 KiB
ArmAsm
158 lines
3.6 KiB
ArmAsm
##
|
|
## This file is part of the "Coroutine" project and released under the MIT License.
|
|
##
|
|
## Created by Samuel Williams on 10/5/2018.
|
|
## Copyright, 2018, by Samuel Williams.
|
|
##
|
|
|
|
/* Important - do _not_ include <cet.h> in this file; doing so will
|
|
* cause an incorrect .note.gnu.property section to be emitted. We have
|
|
* one at the bottom of this file */
|
|
|
|
#define TOKEN_PASTE(x,y) x##y
|
|
|
|
#if defined(__linux__) && defined(__CET__) && (__CET__ & 0x02) != 0
|
|
#define COROUTINE_SHADOW_STACK 1
|
|
#endif
|
|
|
|
.text
|
|
|
|
.globl PREFIXED_SYMBOL(coroutine_transfer)
|
|
PREFIXED_SYMBOL(coroutine_transfer):
|
|
|
|
#if defined(__CET__) && (__CET__ & 0x01) != 0
|
|
/* IBT landing pad */
|
|
endbr64
|
|
#endif
|
|
|
|
# Make space on the stack for 6 registers:
|
|
subq $48, %rsp
|
|
|
|
# Save caller state:
|
|
movq %rbp, 40(%rsp)
|
|
movq %rbx, 32(%rsp)
|
|
movq %r12, 24(%rsp)
|
|
movq %r13, 16(%rsp)
|
|
movq %r14, 8(%rsp)
|
|
movq %r15, (%rsp)
|
|
#if defined(COROUTINE_SHADOW_STACK)
|
|
# A zero target SSP means shadow stacks are not enabled at runtime.
|
|
movq (%rsi), %rax
|
|
cmpq $0, (%rax)
|
|
je 1f
|
|
|
|
# Save the source shadow stack pointer:
|
|
rdsspq %rbp
|
|
pushq %rbp
|
|
jmp 2f
|
|
1:
|
|
pushq $0
|
|
2:
|
|
#endif
|
|
|
|
# Save caller stack pointer:
|
|
movq %rsp, (%rdi)
|
|
|
|
# Restore callee stack pointer:
|
|
movq (%rsi), %rsp
|
|
|
|
#if defined(COROUTINE_SHADOW_STACK)
|
|
# Restore the destination shadow stack pointer:
|
|
popq %rbp
|
|
testq %rbp, %rbp
|
|
jz 3f
|
|
rstorssp -8(%rbp)
|
|
|
|
# Save the source shadow stack pointer token:
|
|
saveprevssp
|
|
3:
|
|
#endif
|
|
|
|
# Restore callee state
|
|
movq 40(%rsp), %rbp
|
|
movq 32(%rsp), %rbx
|
|
movq 24(%rsp), %r12
|
|
movq 16(%rsp), %r13
|
|
movq 8(%rsp), %r14
|
|
movq (%rsp), %r15
|
|
|
|
# Adjust stack pointer back:
|
|
addq $48, %rsp
|
|
|
|
# Put the first argument into the return value:
|
|
movq %rdi, %rax
|
|
|
|
# We pop the return address and jump to it
|
|
ret
|
|
|
|
#if defined(COROUTINE_SHADOW_STACK)
|
|
.globl PREFIXED_SYMBOL(coroutine_initialize_shadow_stack)
|
|
PREFIXED_SYMBOL(coroutine_initialize_shadow_stack):
|
|
#if defined(__CET__) && (__CET__ & 0x01) != 0
|
|
/* IBT landing pad */
|
|
endbr64
|
|
#endif
|
|
# Save the current SSP and switch to the new shadow stack. The restore
|
|
# token created by map_shadow_stack is immediately below the supplied SSP.
|
|
rdsspq %r8
|
|
rstorssp -8(%rdi)
|
|
saveprevssp
|
|
|
|
# CALL is the only way to place an arbitrary return address on a shadow
|
|
# stack without enabling WRSS. Its return address is the trampoline below.
|
|
call 4f
|
|
|
|
.globl PREFIXED_SYMBOL(coroutine_start_trampoline)
|
|
PREFIXED_SYMBOL(coroutine_start_trampoline):
|
|
#if defined(__CET__) && (__CET__ & 0x01) != 0
|
|
/* IBT landing pad */
|
|
endbr64
|
|
#endif
|
|
jmp *%r12
|
|
|
|
4:
|
|
# Remove CALL's entry from the normal stack while retaining its shadow
|
|
# stack entry, then remember the resulting SSP for the new coroutine.
|
|
popq %rax
|
|
rdsspq %rax
|
|
|
|
# Restore the original shadow stack. This leaves a restore token for the
|
|
# newly initialized stack immediately below the SSP returned in %rax.
|
|
rstorssp -8(%r8)
|
|
saveprevssp
|
|
ret
|
|
#endif
|
|
|
|
#if (defined(__linux__) || defined(__FreeBSD__)) && defined(__ELF__)
|
|
.section .note.GNU-stack,"",%progbits
|
|
#endif
|
|
|
|
#if defined(__ELF__)
|
|
|
|
#if defined(__CET__) && (__CET__ & 0x01) != 0
|
|
# define IBT_FLAG 0x01
|
|
#else
|
|
# define IBT_FLAG 0x00
|
|
#endif
|
|
|
|
#if defined(COROUTINE_SHADOW_STACK)
|
|
# define SHSTK_FLAG 0x02
|
|
#else
|
|
# define SHSTK_FLAG 0x00
|
|
#endif
|
|
|
|
.pushsection .note.gnu.property, "a"
|
|
.p2align 3
|
|
.long 0x4 /* Name size ("GNU\0") */
|
|
.long 0x10 /* Descriptor size */
|
|
.long 0x5 /* Type: NT_GNU_PROPERTY_TYPE_0 */
|
|
.asciz "GNU" /* Name */
|
|
# Begin descriptor
|
|
.long 0xc0000002 /* Property type: GNU_PROPERTY_X86_FEATURE_1_AND */
|
|
.long 0x4 /* Property size */
|
|
.long (IBT_FLAG | SHSTK_FLAG)
|
|
.long 0x0 /* 8-byte alignment padding */
|
|
/* End descriptor */
|
|
.popsection
|
|
#endif
|