diff options
Diffstat (limited to 'vendor/psm/src')
23 files changed, 2004 insertions, 0 deletions
diff --git a/vendor/psm/src/arch/aarch64_armasm.asm b/vendor/psm/src/arch/aarch64_armasm.asm new file mode 100644 index 000000000..95349f9cc --- /dev/null +++ b/vendor/psm/src/arch/aarch64_armasm.asm @@ -0,0 +1,38 @@ + AREA |.text|, CODE, READONLY + + GLOBAL |rust_psm_stack_direction| + ALIGN 4 +|rust_psm_stack_direction| PROC + orr w0, wzr, #2 + ret + ENDP + + + GLOBAL |rust_psm_stack_pointer| + ALIGN 4 +|rust_psm_stack_pointer| PROC + mov x0, sp + ret + ENDP + + + GLOBAL |rust_psm_replace_stack| + ALIGN 4 +|rust_psm_replace_stack| PROC + mov sp, x2 + br x1 + ENDP + + GLOBAL |rust_psm_on_stack| + ALIGN 4 +|rust_psm_on_stack| PROC + stp x29, x30, [sp, #-16]! + mov x29, sp + mov sp, x3 + blr x2 + mov sp, x29 + ldp x29, x30, [sp], #16 + ret + ENDP + + END diff --git a/vendor/psm/src/arch/aarch_aapcs64.s b/vendor/psm/src/arch/aarch_aapcs64.s new file mode 100644 index 000000000..55917f329 --- /dev/null +++ b/vendor/psm/src/arch/aarch_aapcs64.s @@ -0,0 +1,85 @@ +#include "psm.h" + +.text + +#if CFG_TARGET_OS_darwin || CFG_TARGET_OS_macos || CFG_TARGET_OS_ios + +#define GLOBL(fnname) .globl _##fnname +#define TYPE(fnname) +#define FUNCTION(fnname) _##fnname +#define SIZE(fnname,endlabel) + +#else + +#define GLOBL(fnname) .globl fnname +#define TYPE(fnname) .type fnname,@function +#define FUNCTION(fnname) fnname +#define SIZE(fnname,endlabel) .size fnname,endlabel-fnname + +#endif + + +GLOBL(rust_psm_stack_direction) +.p2align 2 +TYPE(rust_psm_stack_direction) +FUNCTION(rust_psm_stack_direction): +/* extern "C" fn() -> u8 */ +.cfi_startproc + orr w0, wzr, #STACK_DIRECTION_DESCENDING + ret +.rust_psm_stack_direction_end: +SIZE(rust_psm_stack_direction,.rust_psm_stack_direction_end) +.cfi_endproc + + +GLOBL(rust_psm_stack_pointer) +.p2align 2 +TYPE(rust_psm_stack_pointer) +FUNCTION(rust_psm_stack_pointer): +/* extern "C" fn() -> *mut u8 */ +.cfi_startproc + mov x0, sp + ret +.rust_psm_stack_pointer_end: +SIZE(rust_psm_stack_pointer,.rust_psm_stack_pointer_end) +.cfi_endproc + + +GLOBL(rust_psm_replace_stack) +.p2align 2 +TYPE(rust_psm_replace_stack) +FUNCTION(rust_psm_replace_stack): +/* extern "C" fn(r0: usize, r1: extern "C" fn(usize), r2: *mut u8) */ +.cfi_startproc +/* All we gotta do is set the stack pointer to %rdx & tail-call the callback in %rsi */ + mov sp, x2 + br x1 +.rust_psm_replace_stack_end: +SIZE(rust_psm_replace_stack,.rust_psm_replace_stack_end) +.cfi_endproc + + +GLOBL(rust_psm_on_stack) +.p2align 2 +TYPE(rust_psm_on_stack) +FUNCTION(rust_psm_on_stack): +/* extern "C" fn(r0: usize, r1: usize, r2: extern "C" fn(usize, usize), r3: *mut u8) */ +.cfi_startproc + stp x29, x30, [sp, #-16]! + .cfi_def_cfa sp, 16 + mov x29, sp + .cfi_def_cfa x29, 16 + .cfi_offset x29, -16 + .cfi_offset x30, -8 + mov sp, x3 + blr x2 + mov sp, x29 + .cfi_def_cfa sp, 16 + ldp x29, x30, [sp], #16 + .cfi_def_cfa sp, 0 + .cfi_restore x29 + .cfi_restore x30 + ret +.rust_psm_on_stack_end: +SIZE(rust_psm_on_stack,.rust_psm_on_stack_end) +.cfi_endproc diff --git a/vendor/psm/src/arch/arm_aapcs.s b/vendor/psm/src/arch/arm_aapcs.s new file mode 100644 index 000000000..c2fa9d81d --- /dev/null +++ b/vendor/psm/src/arch/arm_aapcs.s @@ -0,0 +1,106 @@ +#include "psm.h" + +.text +.syntax unified + +#if CFG_TARGET_OS_darwin || CFG_TARGET_OS_macos || CFG_TARGET_OS_ios + +#define GLOBL(fnname) .globl _##fnname +#define THUMBTYPE(fnname) .thumb_func _##fnname +#define FUNCTION(fnname) _##fnname +#define THUMBFN .code 16 +#define SIZE(fnname,endlabel) +#define FNSTART +#define CANTUNWIND +#define FNEND + +#else + +#define GLOBL(fnname) .globl fnname +#define THUMBTYPE(fnname) .type fnname,%function +#define FUNCTION(fnname) fnname +#define THUMBFN .code 16 +#define SIZE(fnname,endlabel) .size fnname,endlabel-fnname +#define FNSTART .fnstart +#define CANTUNWIND .cantunwind +#define FNEND .fnend + +#endif + + +GLOBL(rust_psm_stack_direction) +.p2align 2 +THUMBTYPE(rust_psm_stack_direction) +THUMBFN +FUNCTION(rust_psm_stack_direction): +/* extern "C" fn() -> u8 */ +FNSTART +.cfi_startproc + /* movs to support Thumb-1 */ + movs r0, #STACK_DIRECTION_DESCENDING + bx lr +.rust_psm_stack_direction_end: +SIZE(rust_psm_stack_direction,.rust_psm_stack_direction_end) +.cfi_endproc +CANTUNWIND +FNEND + +GLOBL(rust_psm_stack_pointer) +.p2align 2 +THUMBTYPE(rust_psm_stack_pointer) +THUMBFN +FUNCTION(rust_psm_stack_pointer): +/* extern "C" fn() -> *mut u8 */ +FNSTART +.cfi_startproc + mov r0, sp + bx lr +.rust_psm_stack_pointer_end: +SIZE(rust_psm_stack_pointer,.rust_psm_stack_pointer_end) +.cfi_endproc +CANTUNWIND +FNEND + + +GLOBL(rust_psm_replace_stack) +.p2align 2 +THUMBTYPE(rust_psm_replace_stack) +THUMBFN +FUNCTION(rust_psm_replace_stack): +/* extern "C" fn(r0: usize, r1: extern "C" fn(usize), r2: *mut u8) */ +FNSTART +.cfi_startproc +/* All we gotta do is set the stack pointer to %rdx & tail-call the callback in %rsi */ + mov sp, r2 + bx r1 +.rust_psm_replace_stack_end: +SIZE(rust_psm_replace_stack,.rust_psm_replace_stack_end) +.cfi_endproc +CANTUNWIND +FNEND + + +GLOBL(rust_psm_on_stack) +.p2align 2 +THUMBTYPE(rust_psm_on_stack) +THUMBFN +FUNCTION(rust_psm_on_stack): +/* extern "C" fn(r0: usize, r1: usize, r2: extern "C" fn(usize, usize), r3: *mut u8) */ +FNSTART +.cfi_startproc + push {r4, lr} + .cfi_def_cfa_offset 8 + mov r4, sp + .cfi_def_cfa_register r4 + .cfi_offset lr, -4 + .cfi_offset r4, -8 + mov sp, r3 + blx r2 + mov sp, r4 + .cfi_restore sp + pop {r4, pc} +.rust_psm_on_stack_end: +SIZE(rust_psm_on_stack,.rust_psm_on_stack_end) +.cfi_endproc +CANTUNWIND +FNEND diff --git a/vendor/psm/src/arch/arm_armasm.asm b/vendor/psm/src/arch/arm_armasm.asm new file mode 100644 index 000000000..ab8a5bcf0 --- /dev/null +++ b/vendor/psm/src/arch/arm_armasm.asm @@ -0,0 +1,39 @@ + THUMB + AREA |.text|, CODE, READONLY + + + GLOBAL |rust_psm_stack_direction| + ALIGN 4 +|rust_psm_stack_direction| PROC + movs r0, #2 + bx lr + ENDP + + GLOBAL |rust_psm_stack_pointer| + ALIGN 4 +|rust_psm_stack_pointer| PROC + mov r0, sp + bx lr + ENDP + + + GLOBAL |rust_psm_replace_stack| + ALIGN 4 +|rust_psm_replace_stack| PROC + mov sp, r2 + bx r1 + ENDP + + + GLOBAL |rust_psm_on_stack| + ALIGN 4 +|rust_psm_on_stack| PROC + push {r4, lr} + mov r4, sp + mov sp, r3 + blx r2 + mov sp, r4 + pop {r4, pc} + ENDP + + END diff --git a/vendor/psm/src/arch/mips64_eabi.s b/vendor/psm/src/arch/mips64_eabi.s new file mode 100644 index 000000000..72bc01eb7 --- /dev/null +++ b/vendor/psm/src/arch/mips64_eabi.s @@ -0,0 +1,87 @@ +/* +Not only MIPS has 20 different ABIs... nobody tells anybody what specific variant of which ABI is +used where. + +This is an "EABI" implementation based on the following page: + +http://www.cygwin.com/ml/binutils/2003-06/msg00436.html +*/ + +#include "psm.h" + +.set noreorder /* we’ll manage the delay slots on our own, thanks! */ + +.text +.globl rust_psm_stack_direction +.p2align 3 +.type rust_psm_stack_direction,@function +.ent rust_psm_stack_direction +/* extern "C" fn() -> u8 */ +rust_psm_stack_direction: +.cfi_startproc + jr $31 + addiu $2, $zero, STACK_DIRECTION_DESCENDING +.end rust_psm_stack_direction +.rust_psm_stack_direction_end: +.size rust_psm_stack_direction,.rust_psm_stack_direction_end-rust_psm_stack_direction +.cfi_endproc + + +.globl rust_psm_stack_pointer +.p2align 3 +.type rust_psm_stack_pointer,@function +.ent rust_psm_stack_pointer +/* extern "C" fn() -> *mut u8 */ +rust_psm_stack_pointer: +.cfi_startproc + jr $31 + move $2, $29 +.end rust_psm_stack_pointer +.rust_psm_stack_pointer_end: +.size rust_psm_stack_pointer,.rust_psm_stack_pointer_end-rust_psm_stack_pointer +.cfi_endproc + + + +.globl rust_psm_replace_stack +.p2align 3 +.type rust_psm_replace_stack,@function +.ent rust_psm_replace_stack +/* extern "C" fn(r4: usize, r5: extern "C" fn(usize), r6: *mut u8) */ +rust_psm_replace_stack: +.cfi_startproc + move $25, $5 + jr $5 + move $29, $6 +.end rust_psm_replace_stack +.rust_psm_replace_stack_end: +.size rust_psm_replace_stack,.rust_psm_on_stack_end-rust_psm_on_stack +.cfi_endproc + + +.globl rust_psm_on_stack +.p2align 3 +.type rust_psm_on_stack,@function +.ent rust_psm_on_stack +/* extern "C" fn(r4: usize, r5: usize, r6: extern "C" fn(usize), r7: *mut u8) */ +rust_psm_on_stack: +.cfi_startproc + sd $29, -8($7) + sd $31, -16($7) + .cfi_def_cfa 7, 0 + .cfi_offset 31, -16 + .cfi_offset 29, -8 + move $25, $6 + jalr $31, $6 + daddiu $29, $7, -16 + .cfi_def_cfa 29, 16 + ld $31, 0($29) + .cfi_restore 31 + ld $29, 8($29) + .cfi_restore 29 + jr $31 + nop +.end rust_psm_on_stack +.rust_psm_on_stack_end: +.size rust_psm_on_stack,.rust_psm_on_stack_end-rust_psm_on_stack +.cfi_endproc diff --git a/vendor/psm/src/arch/mips_eabi.s b/vendor/psm/src/arch/mips_eabi.s new file mode 100644 index 000000000..e08ed278a --- /dev/null +++ b/vendor/psm/src/arch/mips_eabi.s @@ -0,0 +1,88 @@ +/* +Not only MIPS has 20 different ABIs... nobody tells anybody what specific variant of which ABI is +used where. + +This is an "EABI" implementation based on the following page: + +http://www.cygwin.com/ml/binutils/2003-06/msg00436.html +*/ + +#include "psm.h" + +.set noreorder /* we’ll manage the delay slots on our own, thanks! */ + +.text +.abicalls +.globl rust_psm_stack_direction +.p2align 2 +.type rust_psm_stack_direction,@function +.ent rust_psm_stack_direction +/* extern "C" fn() -> u8 */ +rust_psm_stack_direction: +.cfi_startproc + jr $31 + addiu $2, $zero, STACK_DIRECTION_DESCENDING +.end rust_psm_stack_direction +.rust_psm_stack_direction_end: +.size rust_psm_stack_direction,.rust_psm_stack_direction_end-rust_psm_stack_direction +.cfi_endproc + + +.globl rust_psm_stack_pointer +.p2align 2 +.type rust_psm_stack_pointer,@function +.ent rust_psm_stack_pointer +/* extern "C" fn() -> *mut u8 */ +rust_psm_stack_pointer: +.cfi_startproc + jr $31 + move $2, $29 +.end rust_psm_stack_pointer +.rust_psm_stack_pointer_end: +.size rust_psm_stack_pointer,.rust_psm_stack_pointer_end-rust_psm_stack_pointer +.cfi_endproc + + + +.globl rust_psm_replace_stack +.p2align 2 +.type rust_psm_replace_stack,@function +.ent rust_psm_replace_stack +/* extern "C" fn(r4: usize, r5: extern "C" fn(usize), r6: *mut u8) */ +rust_psm_replace_stack: +.cfi_startproc + move $25, $5 + jr $5 + move $29, $6 +.end rust_psm_replace_stack +.rust_psm_replace_stack_end: +.size rust_psm_replace_stack,.rust_psm_on_stack_end-rust_psm_on_stack +.cfi_endproc + + +.globl rust_psm_on_stack +.p2align 2 +.type rust_psm_on_stack,@function +.ent rust_psm_on_stack +/* extern "C" fn(r4: usize, r5: usize, r6: extern "C" fn(usize), r7: *mut u8) */ +rust_psm_on_stack: +.cfi_startproc + sw $29, -4($7) + sw $31, -8($7) + .cfi_def_cfa 7, 0 + .cfi_offset 31, -8 + .cfi_offset 29, -4 + move $25, $6 + jalr $31, $6 + addiu $29, $7, -8 + .cfi_def_cfa 29, 8 + lw $31, 0($29) + .cfi_restore 31 + lw $29, 4($29) + .cfi_restore 29 + jr $31 + nop +.end rust_psm_on_stack +.rust_psm_on_stack_end: +.size rust_psm_on_stack,.rust_psm_on_stack_end-rust_psm_on_stack +.cfi_endproc diff --git a/vendor/psm/src/arch/powerpc32.s b/vendor/psm/src/arch/powerpc32.s new file mode 100644 index 000000000..1f7a08619 --- /dev/null +++ b/vendor/psm/src/arch/powerpc32.s @@ -0,0 +1,76 @@ +#include "psm.h" +/* FIXME: this probably does not cover all ABIs? Tested with sysv only, possibly works for AIX as + well? +*/ + +.text +.globl rust_psm_stack_direction +.p2align 2 +.type rust_psm_stack_direction,@function +rust_psm_stack_direction: +/* extern "C" fn() -> u8 */ +.cfi_startproc + li 3, STACK_DIRECTION_DESCENDING + blr +.rust_psm_stack_direction_end: +.size rust_psm_stack_direction,.rust_psm_stack_direction_end-rust_psm_stack_direction +.cfi_endproc + + +.globl rust_psm_stack_pointer +.p2align 2 +.type rust_psm_stack_pointer,@function +rust_psm_stack_pointer: +/* extern "C" fn() -> *mut u8 */ +.cfi_startproc + mr 3, 1 + blr +.rust_psm_stack_pointer_end: +.size rust_psm_stack_pointer,.rust_psm_stack_pointer_end-rust_psm_stack_pointer +.cfi_endproc + + +.globl rust_psm_replace_stack +.p2align 2 +.type rust_psm_replace_stack,@function +rust_psm_replace_stack: +/* extern "C" fn(3: usize, 4: extern "C" fn(usize), 5: *mut u8) */ +.cfi_startproc +/* NOTE: perhaps add a debug-assertion for stack alignment? */ + addi 5, 5, -16 + mr 1, 5 + mtctr 4 + bctr +.rust_psm_replace_stack_end: +.size rust_psm_replace_stack,.rust_psm_replace_stack_end-rust_psm_replace_stack +.cfi_endproc + + +.globl rust_psm_on_stack +.p2align 2 +.type rust_psm_on_stack,@function +rust_psm_on_stack: +/* extern "C" fn(3: usize, 4: usize, 5: extern "C" fn(usize, usize), 6: *mut u8) */ +.cfi_startproc + mflr 0 + stw 0, -24(6) + sub 6, 6, 1 + addi 6, 6, -32 + stwux 1, 1, 6 + .cfi_def_cfa r1, 32 + .cfi_offset r1, -32 + .cfi_offset lr, -24 + mtctr 5 + bctrl + lwz 0, 8(1) + mtlr 0 + .cfi_restore lr + /* FIXME: after this instruction backtrace breaks until control returns to the caller + That being said compiler-generated code has the same issue, so I guess that is fine for now? + */ + lwz 1, 0(1) + .cfi_restore r1 + blr +.rust_psm_on_stack_end: +.size rust_psm_on_stack,.rust_psm_on_stack_end-rust_psm_on_stack +.cfi_endproc diff --git a/vendor/psm/src/arch/powerpc64.s b/vendor/psm/src/arch/powerpc64.s new file mode 100644 index 000000000..1504a8c01 --- /dev/null +++ b/vendor/psm/src/arch/powerpc64.s @@ -0,0 +1,90 @@ +/* Implementation of the AIX-like PowerPC ABI. Seems to be used by the big-endian PowerPC targets. + The following references were used during the implementation of this code: + + https://www.ibm.com/support/knowledgecenter/en/ssw_aix_72/com.ibm.aix.alangref/idalangref_rntime_stack.htm + https://www.ibm.com/support/knowledgecenter/en/ssw_aix_72/com.ibm.aix.alangref/idalangref_reg_use_conv.htm + https://www.ibm.com/developerworks/library/l-powasm4/index.html +*/ + +#include "psm.h" + +.text +.globl rust_psm_stack_direction +.p2align 2 +.type rust_psm_stack_direction,@function +rust_psm_stack_direction: +/* extern "C" fn() -> u8 */ +.cfi_startproc + li 3, STACK_DIRECTION_DESCENDING + blr +.rust_psm_stack_direction_end: +.size rust_psm_stack_direction,.rust_psm_stack_direction_end-rust_psm_stack_direction +.cfi_endproc + + +.globl rust_psm_stack_pointer +.p2align 2 +.type rust_psm_stack_pointer,@function +rust_psm_stack_pointer: +/* extern "C" fn() -> *mut u8 */ +.cfi_startproc + mr 3, 1 + blr +.rust_psm_stack_pointer_end: +.size rust_psm_stack_pointer,.rust_psm_stack_pointer_end-rust_psm_stack_pointer +.cfi_endproc + + +.globl rust_psm_replace_stack +.p2align 2 +.type rust_psm_replace_stack,@function +rust_psm_replace_stack: +/* extern "C" fn(3: usize, 4: extern "C" fn(usize), 5: *mut u8) */ +.cfi_startproc + ld 2, 8(4) + ld 4, 0(4) + /* do not allocate the whole 112-byte sized frame, we know wont be used */ + addi 5, 5, -48 + mr 1, 5 + mtctr 4 + bctr +.rust_psm_replace_stack_end: +.size rust_psm_replace_stack,.rust_psm_replace_stack_end-rust_psm_replace_stack +.cfi_endproc + + +.globl rust_psm_on_stack +.p2align 2 +.type rust_psm_on_stack,@function +rust_psm_on_stack: +/* extern "C" fn(3: usize, 4: usize, 5: extern "C" fn(usize, usize), 6: *mut u8) */ +.cfi_startproc + mflr 0 + std 2, -72(6) + std 0, -8(6) + sub 6, 6, 1 + addi 6, 6, -112 + stdux 1, 1, 6 + .cfi_def_cfa r1, 112 + .cfi_offset r1, -112 + .cfi_offset r2, -72 + .cfi_offset lr, -8 + /* load the function pointer from TOC and make the call */ + ld 2, 8(5) + ld 5, 0(5) + mtctr 5 + bctrl + ld 2, 40(1) + .cfi_restore r2 + ld 0, 104(1) + mtlr 0 + .cfi_restore lr + /* FIXME: after this instruction backtrace breaks until control returns to the caller. + That being said compiler-generated code has the same issue, so I guess that is fine for now? + */ + ld 1, 0(1) + .cfi_restore r1 + blr +.rust_psm_on_stack_end: +.size rust_psm_on_stack,.rust_psm_on_stack_end-rust_psm_on_stack +.cfi_endproc diff --git a/vendor/psm/src/arch/powerpc64_openpower.s b/vendor/psm/src/arch/powerpc64_openpower.s new file mode 100644 index 000000000..eb3c1c174 --- /dev/null +++ b/vendor/psm/src/arch/powerpc64_openpower.s @@ -0,0 +1,86 @@ +/* Implementation of stack swtiching routines for OpenPOWER 64-bit ELF ABI + The specification can be found at + http://openpowerfoundation.org/wp-content/uploads/resources/leabi/content/ch_preface.html + + This ABI is usually used by the ppc64le targets. +*/ + +#include "psm.h" + +.text +.abiversion 2 + + +.globl rust_psm_stack_direction +.p2align 4 +.type rust_psm_stack_direction,@function +rust_psm_stack_direction: +/* extern "C" fn() -> u8 */ +.cfi_startproc + li 3, STACK_DIRECTION_DESCENDING + blr +.rust_psm_stack_direction_end: +.size rust_psm_stack_direction,.rust_psm_stack_direction_end-rust_psm_stack_direction +.cfi_endproc + + +.globl rust_psm_stack_pointer +.p2align 4 +.type rust_psm_stack_pointer,@function +rust_psm_stack_pointer: +/* extern "C" fn() -> *mut u8 */ +.cfi_startproc + mr 3, 1 + blr +.rust_psm_stack_pointer_end: +.size rust_psm_stack_pointer,.rust_psm_stack_pointer_end-rust_psm_stack_pointer +.cfi_endproc + + +.globl rust_psm_replace_stack +.p2align 4 +.type rust_psm_replace_stack,@function +rust_psm_replace_stack: +/* extern "C" fn(3: usize, 4: extern "C" fn(usize), 5: *mut u8) */ +.cfi_startproc + addi 5, 5, -32 + mtctr 4 + mr 12, 4 + mr 1, 5 + bctr +.rust_psm_replace_stack_end: +.size rust_psm_replace_stack,.rust_psm_replace_stack_end-rust_psm_replace_stack +.cfi_endproc + + + +.globl rust_psm_on_stack +.p2align 4 +.type rust_psm_on_stack,@function +rust_psm_on_stack: +/* extern "C" fn(3: usize, 4: usize, 5: extern "C" fn(usize, usize), 6: *mut u8) */ +.cfi_startproc + mflr 0 + std 0, -8(6) + std 2, -24(6) + sub 6, 6, 1 + addi 6, 6, -48 + stdux 1, 1, 6 + .cfi_def_cfa r1, 48 + .cfi_offset r1, -48 + .cfi_offset r2, -24 + .cfi_offset lr, -8 + mr 12, 5 + mtctr 5 + bctrl + ld 2, 24(1) + .cfi_restore r2 + ld 0, 40(1) + mtlr 0 + .cfi_restore lr + /* FIXME: after this instructin backtrace breaks until control returns to the caller */ + ld 1, 0(1) + blr +.rust_psm_on_stack_end: +.size rust_psm_on_stack,.rust_psm_on_stack_end-rust_psm_on_stack +.cfi_endproc diff --git a/vendor/psm/src/arch/psm.h b/vendor/psm/src/arch/psm.h new file mode 100644 index 000000000..c1137f984 --- /dev/null +++ b/vendor/psm/src/arch/psm.h @@ -0,0 +1,10 @@ +#define STACK_DIRECTION_ASCENDING 1 +#define STACK_DIRECTION_DESCENDING 2 + + +/* +Various defines for values produced by `-DCFG_TARGET_*` flags. Only needs to be mutually unique +*/ +#define darwin 1 +#define macos 2 +#define ios 3 diff --git a/vendor/psm/src/arch/riscv.s b/vendor/psm/src/arch/riscv.s new file mode 100644 index 000000000..4972993c9 --- /dev/null +++ b/vendor/psm/src/arch/riscv.s @@ -0,0 +1,64 @@ +#include "psm.h" + +.text +.globl rust_psm_stack_direction +.p2align 2 +.type rust_psm_stack_direction,@function +rust_psm_stack_direction: +/* extern "C" fn() -> u8 */ +.cfi_startproc + li x10, STACK_DIRECTION_DESCENDING + jr x1 +.rust_psm_stack_direction_end: +.size rust_psm_stack_direction,.rust_psm_stack_direction_end-rust_psm_stack_direction +.cfi_endproc + + +.globl rust_psm_stack_pointer +.p2align 2 +.type rust_psm_stack_pointer,@function +rust_psm_stack_pointer: +/* extern "C" fn() -> *mut u8 */ +.cfi_startproc + add x10, x2, x0 + jr x1 +.rust_psm_stack_pointer_end: +.size rust_psm_stack_pointer,.rust_psm_stack_pointer_end-rust_psm_stack_pointer +.cfi_endproc + + +.globl rust_psm_replace_stack +.p2align 2 +.type rust_psm_replace_stack,@function +rust_psm_replace_stack: +/* extern "C" fn(x10: usize, x11: extern "C" fn(usize), x12: *mut u8) */ +.cfi_startproc + add x2, x12, x0 + jr x11 +.rust_psm_replace_stack_end: +.size rust_psm_replace_stack,.rust_psm_replace_stack_end-rust_psm_replace_stack +.cfi_endproc + + +.globl rust_psm_on_stack +.p2align 2 +.type rust_psm_on_stack,@function +rust_psm_on_stack: +/* extern "C" fn(x10: usize, x11: usize, x12: extern "C" fn(usize, usize), x13: *mut u8) */ +.cfi_startproc + sw x1, -12(x13) + sw x2, -16(x13) + .cfi_def_cfa x13, 0 + .cfi_offset x1, -12 + .cfi_offset x2, -16 + addi x2, x13, -16 + .cfi_def_cfa x2, -16 + jalr x1, x12, 0 + lw x1, 4(x2) + .cfi_restore x1 + lw x2, 0(x2) + .cfi_restore x2 + jr x1 +.rust_psm_on_stack_end: +.size rust_psm_on_stack,.rust_psm_on_stack_end-rust_psm_on_stack +.cfi_endproc diff --git a/vendor/psm/src/arch/riscv64.s b/vendor/psm/src/arch/riscv64.s new file mode 100644 index 000000000..1b275ec27 --- /dev/null +++ b/vendor/psm/src/arch/riscv64.s @@ -0,0 +1,64 @@ +#include "psm.h" + +.text +.globl rust_psm_stack_direction +.p2align 2 +.type rust_psm_stack_direction,@function +rust_psm_stack_direction: +/* extern "C" fn() -> u8 */ +.cfi_startproc + li x10, STACK_DIRECTION_DESCENDING + jr x1 +.rust_psm_stack_direction_end: +.size rust_psm_stack_direction,.rust_psm_stack_direction_end-rust_psm_stack_direction +.cfi_endproc + + +.globl rust_psm_stack_pointer +.p2align 2 +.type rust_psm_stack_pointer,@function +rust_psm_stack_pointer: +/* extern "C" fn() -> *mut u8 */ +.cfi_startproc + add x10, x2, x0 + jr x1 +.rust_psm_stack_pointer_end: +.size rust_psm_stack_pointer,.rust_psm_stack_pointer_end-rust_psm_stack_pointer +.cfi_endproc + + +.globl rust_psm_replace_stack +.p2align 2 +.type rust_psm_replace_stack,@function +rust_psm_replace_stack: +/* extern "C" fn(x10: usize, x11: extern "C" fn(usize), x12: *mut u8) */ +.cfi_startproc + add x2, x12, x0 + jr x11 +.rust_psm_replace_stack_end: +.size rust_psm_replace_stack,.rust_psm_replace_stack_end-rust_psm_replace_stack +.cfi_endproc + + +.globl rust_psm_on_stack +.p2align 2 +.type rust_psm_on_stack,@function +rust_psm_on_stack: +/* extern "C" fn(x10: usize, x11: usize, x12: extern "C" fn(usize, usize), x13: *mut u8) */ +.cfi_startproc + sd x1, -8(x13) + sd x2, -16(x13) + .cfi_def_cfa x13, 0 + .cfi_offset x1, -8 + .cfi_offset x2, -16 + addi x2, x13, -16 + .cfi_def_cfa x2, -16 + jalr x1, x12, 0 + ld x1, 8(x2) + .cfi_restore x1 + ld x2, 0(x2) + .cfi_restore x2 + jr x1 +.rust_psm_on_stack_end: +.size rust_psm_on_stack,.rust_psm_on_stack_end-rust_psm_on_stack +.cfi_endproc diff --git a/vendor/psm/src/arch/sparc64.s b/vendor/psm/src/arch/sparc64.s new file mode 100644 index 000000000..a0db27dde --- /dev/null +++ b/vendor/psm/src/arch/sparc64.s @@ -0,0 +1,67 @@ +#include "psm.h" + +.text +.globl rust_psm_stack_direction +.p2align 2 +.type rust_psm_stack_direction,@function +rust_psm_stack_direction: +/* extern "C" fn() -> u8 */ +.cfi_startproc + jmpl %o7 + 8, %g0 + mov STACK_DIRECTION_DESCENDING, %o0 +.rust_psm_stack_direction_end: +.size rust_psm_stack_direction,.rust_psm_stack_direction_end-rust_psm_stack_direction +.cfi_endproc + + +.globl rust_psm_stack_pointer +.p2align 2 +.type rust_psm_stack_pointer,@function +rust_psm_stack_pointer: +/* extern "C" fn() -> *mut u8 */ +.cfi_startproc + jmpl %o7 + 8, %g0 + mov %o6, %o0 +.rust_psm_stack_pointer_end: +.size rust_psm_stack_pointer,.rust_psm_stack_pointer_end-rust_psm_stack_pointer +.cfi_endproc + + +.globl rust_psm_replace_stack +.p2align 2 +.type rust_psm_replace_stack,@function +rust_psm_replace_stack: +/* extern "C" fn(%i0: usize, %i1: extern "C" fn(usize), %i2: *mut u8) */ +.cfi_startproc + .cfi_def_cfa 0, 0 + .cfi_return_column 0 + jmpl %o1, %g0 + /* WEIRD: Why is the LSB set for the %sp and %fp on SPARC?? */ + add %o2, -0x7ff, %o6 +.rust_psm_replace_stack_end: +.size rust_psm_replace_stack,.rust_psm_replace_stack_end-rust_psm_replace_stack +.cfi_endproc + + +.globl rust_psm_on_stack +.p2align 2 +.type rust_psm_on_stack,@function +rust_psm_on_stack: +/* extern "C" fn(%i0: usize, %i1: usize, %i2: extern "C" fn(usize, usize), %i3: *mut u8) */ +.cfi_startproc + /* The fact that locals and saved register windows are offset by 2kB is + very nasty property of SPARC architecture and ABI. In this case it forces us to slice off + 2kB of the stack space outright for no good reason other than adapting to a botched design. + */ + save %o3, -0x87f, %o6 + .cfi_def_cfa_register %fp + .cfi_window_save + .cfi_register %r15, %r31 + mov %i1, %o1 + jmpl %i2, %o7 + mov %i0, %o0 + ret + restore +.rust_psm_on_stack_end: +.size rust_psm_on_stack,.rust_psm_on_stack_end-rust_psm_on_stack +.cfi_endproc diff --git a/vendor/psm/src/arch/sparc_sysv.s b/vendor/psm/src/arch/sparc_sysv.s new file mode 100644 index 000000000..27d95e933 --- /dev/null +++ b/vendor/psm/src/arch/sparc_sysv.s @@ -0,0 +1,65 @@ +#include "psm.h" + +/* FIXME: this ABI has definitely not been verified at all */ + +.text +.globl rust_psm_stack_direction +.p2align 2 +.type rust_psm_stack_direction,@function +rust_psm_stack_direction: +/* extern "C" fn() -> u8 */ +.cfi_startproc + jmpl %o7 + 8, %g0 + mov STACK_DIRECTION_DESCENDING, %o0 +.rust_psm_stack_direction_end: +.size rust_psm_stack_direction,.rust_psm_stack_direction_end-rust_psm_stack_direction +.cfi_endproc + + +.globl rust_psm_stack_pointer +.p2align 2 +.type rust_psm_stack_pointer,@function +rust_psm_stack_pointer: +/* extern "C" fn() -> *mut u8 */ +.cfi_startproc + jmpl %o7 + 8, %g0 + mov %o6, %o0 +.rust_psm_stack_pointer_end: +.size rust_psm_stack_pointer,.rust_psm_stack_pointer_end-rust_psm_stack_pointer +.cfi_endproc + + +.globl rust_psm_replace_stack +.p2align 2 +.type rust_psm_replace_stack,@function +rust_psm_replace_stack: +/* extern "C" fn(%i0: usize, %i1: extern "C" fn(usize), %i2: *mut u8) */ +.cfi_startproc + .cfi_def_cfa 0, 0 + .cfi_return_column 0 + jmpl %o1, %g0 + /* WEIRD: Why is the LSB set for the %sp and %fp on SPARC?? */ + add %o2, -0x3ff, %o6 +.rust_psm_replace_stack_end: +.size rust_psm_replace_stack,.rust_psm_replace_stack_end-rust_psm_replace_stack +.cfi_endproc + + +.globl rust_psm_on_stack +.p2align 2 +.type rust_psm_on_stack,@function +rust_psm_on_stack: +/* extern "C" fn(%i0: usize, %i1: usize, %i2: extern "C" fn(usize, usize), %i3: *mut u8) */ +.cfi_startproc + save %o3, -0x43f, %o6 + .cfi_def_cfa_register %fp + .cfi_window_save + .cfi_register %r15, %r31 + mov %i1, %o1 + jmpl %i2, %o7 + mov %i0, %o0 + ret + restore +.rust_psm_on_stack_end: +.size rust_psm_on_stack,.rust_psm_on_stack_end-rust_psm_on_stack +.cfi_endproc diff --git a/vendor/psm/src/arch/wasm32.s b/vendor/psm/src/arch/wasm32.s new file mode 100644 index 000000000..e3364e7af --- /dev/null +++ b/vendor/psm/src/arch/wasm32.s @@ -0,0 +1,60 @@ +#include "psm.h" + +# Note that this function is not compiled when this package is uploaded to +# crates.io, this source is only here as a reference for how the corresponding +# wasm32.o was generated. This file can be compiled with: +# +# cpp psm/src/arch/wasm32.s | llvm-mc -o psm/src/arch/wasm32.o --arch=wasm32 -filetype=obj +# +# where you'll want to ensure that `llvm-mc` is from a relatively recent +# version of LLVM. + +.globaltype __stack_pointer, i32 + +.globl rust_psm_stack_direction +.type rust_psm_stack_direction,@function +rust_psm_stack_direction: +.functype rust_psm_stack_direction () -> (i32) + i32.const STACK_DIRECTION_DESCENDING + end_function + +.globl rust_psm_stack_pointer +.type rust_psm_stack_pointer,@function +rust_psm_stack_pointer: +.functype rust_psm_stack_pointer () -> (i32) + global.get __stack_pointer + end_function + +.globl rust_psm_on_stack +.type rust_psm_on_stack,@function +rust_psm_on_stack: +.functype rust_psm_on_stack (i32, i32, i32, i32) -> () + # get our new stack argument, then save the old stack + # pointer into that local + local.get 3 + global.get __stack_pointer + local.set 3 + global.set __stack_pointer + + # Call our indirect function specified + local.get 0 + local.get 1 + local.get 2 + call_indirect (i32, i32) -> () + + # restore the stack pointer before returning + local.get 3 + global.set __stack_pointer + end_function + +.globl rust_psm_replace_stack +.type rust_psm_replace_stack,@function +rust_psm_replace_stack: +.functype rust_psm_replace_stack (i32, i32, i32) -> () + local.get 2 + global.set __stack_pointer + local.get 0 + local.get 1 + call_indirect (i32) -> () + unreachable + end_function diff --git a/vendor/psm/src/arch/x86.s b/vendor/psm/src/arch/x86.s new file mode 100644 index 000000000..2e388760d --- /dev/null +++ b/vendor/psm/src/arch/x86.s @@ -0,0 +1,91 @@ +#include "psm.h" +/* NOTE: fastcall calling convention used on all x86 targets */ + +.text + +#if CFG_TARGET_OS_darwin || CFG_TARGET_OS_macos || CFG_TARGET_OS_ios + +#define GLOBL(fnname) .globl _##fnname +#define TYPE(fnname) +#define FUNCTION(fnname) _##fnname +#define SIZE(fnname,endlabel) + +#else + +#define GLOBL(fnname) .globl fnname +#define TYPE(fnname) .type fnname,@function +#define FUNCTION(fnname) fnname +#define SIZE(fnname,endlabel) .size fnname,endlabel-fnname + +#endif + + +GLOBL(rust_psm_stack_direction) +.p2align 4 +TYPE(rust_psm_stack_direction) +FUNCTION(rust_psm_stack_direction): +/* extern "fastcall" fn() -> u8 (%al) */ +.cfi_startproc + movb $STACK_DIRECTION_DESCENDING, %al # always descending on x86_64 + retl +.rust_psm_stack_direction_end: +SIZE(rust_psm_stack_direction,.rust_psm_stack_direction_end) +.cfi_endproc + + +GLOBL(rust_psm_stack_pointer) +.p2align 4 +TYPE(rust_psm_stack_pointer) +FUNCTION(rust_psm_stack_pointer): +/* extern "fastcall" fn() -> *mut u8 (%rax) */ +.cfi_startproc + leal 4(%esp), %eax + retl +.rust_psm_stack_pointer_end: +SIZE(rust_psm_stack_pointer,.rust_psm_stack_pointer_end) +.cfi_endproc + + +GLOBL(rust_psm_replace_stack) +.p2align 4 +TYPE(rust_psm_replace_stack) +FUNCTION(rust_psm_replace_stack): +/* extern "fastcall" fn(%ecx: usize, %edx: extern "fastcall" fn(usize), 4(%esp): *mut u8) */ +.cfi_startproc +/* + All we gotta do is set the stack pointer to 4(%esp) & tail-call the callback in %edx + + Note, that the callee expects the stack to be offset by 4 bytes (normally, a return address + would be store there) off the required stack alignment on entry. To offset the stack in such a + way we use the `calll` instruction, however it would also be possible to to use plain `jmpl` but + would require to adjust the stack manually, which cannot be easily done, because the stack + pointer argument is already stored in memory. + */ + movl 4(%esp), %esp + calll *%edx + ud2 +.rust_psm_replace_stack_end: +SIZE(rust_psm_replace_stack,.rust_psm_replace_stack_end) +.cfi_endproc + + +GLOBL(rust_psm_on_stack) +.p2align 4 +TYPE(rust_psm_on_stack) +FUNCTION(rust_psm_on_stack): +/* extern "fastcall" fn(%ecx: usize, %edx: usize, 4(%esp): extern "fastcall" fn(usize, usize), 8(%esp): *mut u8) */ +.cfi_startproc + pushl %ebp + .cfi_def_cfa %esp, 8 + .cfi_offset %ebp, -8 + movl %esp, %ebp + .cfi_def_cfa_register %ebp + movl 12(%ebp), %esp + calll *8(%ebp) + movl %ebp, %esp + popl %ebp + .cfi_def_cfa %esp, 4 + retl $8 +.rust_psm_on_stack_end: +SIZE(rust_psm_on_stack,.rust_psm_on_stack_end) +.cfi_endproc diff --git a/vendor/psm/src/arch/x86_64.s b/vendor/psm/src/arch/x86_64.s new file mode 100644 index 000000000..5f5ece5b1 --- /dev/null +++ b/vendor/psm/src/arch/x86_64.s @@ -0,0 +1,87 @@ +#include "psm.h" +/* NOTE: sysv64 calling convention is used on all x86_64 targets, including Windows! */ + +.text + +#if CFG_TARGET_OS_darwin || CFG_TARGET_OS_macos || CFG_TARGET_OS_ios + +#define GLOBL(fnname) .globl _##fnname +#define TYPE(fnname) +#define FUNCTION(fnname) _##fnname +#define SIZE(fnname,endlabel) + +#else + +#define GLOBL(fnname) .globl fnname +#define TYPE(fnname) .type fnname,@function +#define FUNCTION(fnname) fnname +#define SIZE(fnname,endlabel) .size fnname,endlabel-fnname + +#endif + + +GLOBL(rust_psm_stack_direction) +.p2align 4 +TYPE(rust_psm_stack_direction) +FUNCTION(rust_psm_stack_direction): +/* extern "sysv64" fn() -> u8 (%al) */ +.cfi_startproc + movb $STACK_DIRECTION_DESCENDING, %al # always descending on x86_64 + retq +.rust_psm_stack_direction_end: +SIZE(rust_psm_stack_direction,.rust_psm_stack_direction_end) +.cfi_endproc + + +GLOBL(rust_psm_stack_pointer) +.p2align 4 +TYPE(rust_psm_stack_pointer) +FUNCTION(rust_psm_stack_pointer): +/* extern "sysv64" fn() -> *mut u8 (%rax) */ +.cfi_startproc + leaq 8(%rsp), %rax + retq +.rust_psm_stack_pointer_end: +SIZE(rust_psm_stack_pointer,.rust_psm_stack_pointer_end) +.cfi_endproc + + +GLOBL(rust_psm_replace_stack) +.p2align 4 +TYPE(rust_psm_replace_stack) +FUNCTION(rust_psm_replace_stack): +/* extern "sysv64" fn(%rdi: usize, %rsi: extern "sysv64" fn(usize), %rdx: *mut u8) */ +.cfi_startproc +/* + All we gotta do is set the stack pointer to %rdx & tail-call the callback in %rsi. + + 8-byte offset necessary to account for the "return" pointer that would otherwise be placed onto + stack with a regular call +*/ + leaq -8(%rdx), %rsp + jmpq *%rsi +.rust_psm_replace_stack_end: +SIZE(rust_psm_replace_stack,.rust_psm_replace_stack_end) +.cfi_endproc + + +GLOBL(rust_psm_on_stack) +.p2align 4 +TYPE(rust_psm_on_stack) +FUNCTION(rust_psm_on_stack): +/* extern "sysv64" fn(%rdi: usize, %rsi: usize, %rdx: extern "sysv64" fn(usize, usize), %rcx: *mut u8) */ +.cfi_startproc + pushq %rbp + .cfi_def_cfa %rsp, 16 + .cfi_offset %rbp, -16 + movq %rsp, %rbp + .cfi_def_cfa_register %rbp + movq %rcx, %rsp + callq *%rdx + movq %rbp, %rsp + popq %rbp + .cfi_def_cfa %rsp, 8 + retq +.rust_psm_on_stack_end: +SIZE(rust_psm_on_stack,.rust_psm_on_stack_end) +.cfi_endproc diff --git a/vendor/psm/src/arch/x86_64_msvc.asm b/vendor/psm/src/arch/x86_64_msvc.asm new file mode 100644 index 000000000..67d72832f --- /dev/null +++ b/vendor/psm/src/arch/x86_64_msvc.asm @@ -0,0 +1,61 @@ +PUBLIC rust_psm_stack_direction +PUBLIC rust_psm_stack_pointer +PUBLIC rust_psm_replace_stack +PUBLIC rust_psm_on_stack + +_TEXT SEGMENT + +; extern "sysv64" fn() -> u8 (%al) +rust_psm_stack_direction PROC + mov al, 2 + ret +rust_psm_stack_direction ENDP + +; extern "sysv64" fn() -> *mut u8 (%rax) +rust_psm_stack_pointer PROC + lea rax, [rsp + 8] + ret +rust_psm_stack_pointer ENDP + +; extern "sysv64" fn(%rdi: usize, %rsi: extern "sysv64" fn(usize), %rdx: *mut u8, %rcx: *mut u8) +rust_psm_replace_stack PROC + mov gs:[08h], rdx + mov gs:[10h], rcx + lea rsp, [rdx - 8] + jmp rsi +rust_psm_replace_stack ENDP + +; extern "sysv64" fn(%rdi: usize, %rsi: usize, +; %rdx: extern "sysv64" fn(usize, usize), %rcx: *mut u8, %r8: *mut u8) +; +; NB: on Windows for SEH to work at all, the pointers in TIB, thread information block, need to be +; fixed up. Otherwise, it seems that exception mechanism on Windows will not bother looking for +; exception handlers at *all* if they happen to fall outside the are specified in TIB. +; +; This necessitates an API difference from the usual 4-argument signature used elsewhere. +; +; FIXME: this needs a catch-all exception handler that aborts in case somebody unwinds into here. +rust_psm_on_stack PROC FRAME + push rbp + .pushreg rbp + mov rbp, rsp + .setframe rbp, 0 + .endprolog + + push gs:[08h] + mov gs:[08h], rcx + push gs:[10h] + mov gs:[10h], r8 + mov rsp, rcx + call rdx + lea rsp, [rbp - 010h] + pop gs:[10h] + pop gs:[08h] + + pop rbp + ret +rust_psm_on_stack ENDP + +_TEXT ENDS + +END diff --git a/vendor/psm/src/arch/x86_64_windows_gnu.s b/vendor/psm/src/arch/x86_64_windows_gnu.s new file mode 100644 index 000000000..8f1258356 --- /dev/null +++ b/vendor/psm/src/arch/x86_64_windows_gnu.s @@ -0,0 +1,95 @@ +.text + +.def rust_psm_stack_direction +.scl 2 +.type 32 +.endef +.globl rust_psm_stack_direction +.p2align 4 +rust_psm_stack_direction: +/* extern "sysv64" fn() -> u8 (%al) */ +.cfi_startproc + movb $2, %al # always descending on x86_64 + retq +.cfi_endproc + +.def rust_psm_stack_pointer +.scl 2 +.type 32 +.endef +.globl rust_psm_stack_pointer +.p2align 4 +rust_psm_stack_pointer: +/* extern "sysv64" fn() -> *mut u8 (%rax) */ +.cfi_startproc + leaq 8(%rsp), %rax + retq +.cfi_endproc + + +.def rust_psm_replace_stack +.scl 2 +.type 32 +.endef +.globl rust_psm_replace_stack +.p2align 4 +rust_psm_replace_stack: +/* extern "sysv64" fn(%rdi: usize, %rsi: extern "sysv64" fn(usize), %rdx: *mut u8, %rcx: *mut u8) */ +.cfi_startproc +/* + All we gotta do is set the stack pointer to %rdx & tail-call the callback in %rsi. + + 8-byte offset necessary to account for the "return" pointer that would otherwise be placed onto + stack with a regular call +*/ + movq %gs:0x08, %rdx + movq %gs:0x10, %rcx + leaq -8(%rdx), %rsp + jmpq *%rsi +.cfi_endproc + + +.def rust_psm_on_stack +.scl 2 +.type 32 +.endef +.globl rust_psm_on_stack +.p2align 4 +rust_psm_on_stack: +/* +extern "sysv64" fn(%rdi: usize, %rsi: usize, + %rdx: extern "sysv64" fn(usize, usize), %rcx: *mut u8, %r8: *mut u8) + +NB: on Windows for SEH to work at all, the pointers in TIB, thread information block, need to be +fixed up. Otherwise, it seems that exception mechanism on Windows will not bother looking for +exception handlers at *all* if they happen to fall outside the are specified in TIB. + +This necessitates an API difference from the usual 4-argument signature used elsewhere. + +FIXME: this needs a catch-all exception handler that aborts in case somebody unwinds into here. +*/ +.cfi_startproc + pushq %rbp + .cfi_def_cfa %rsp, 16 + .cfi_offset %rbp, -16 + pushq %gs:0x08 + .cfi_def_cfa %rsp, 24 + pushq %gs:0x10 + .cfi_def_cfa %rsp, 32 + + movq %rsp, %rbp + .cfi_def_cfa_register %rbp + movq %rcx, %gs:0x08 + movq %r8, %gs:0x10 + movq %rcx, %rsp + callq *%rdx + movq %rbp, %rsp + + popq %gs:0x10 + .cfi_def_cfa %rsp, 24 + popq %gs:0x08 + .cfi_def_cfa %rsp, 16 + popq %rbp + .cfi_def_cfa %rsp, 8 + retq +.cfi_endproc diff --git a/vendor/psm/src/arch/x86_msvc.asm b/vendor/psm/src/arch/x86_msvc.asm new file mode 100644 index 000000000..3838759f7 --- /dev/null +++ b/vendor/psm/src/arch/x86_msvc.asm @@ -0,0 +1,70 @@ +; FIXME: this is weird, this works locally but not on appveyor?!??! + +.386 +.model flat + +ASSUME FS:NOTHING + +; WTF: PUBLIC conflicts with "SYSCALL" but "SYSCALL" is the only way to stop MASM from manging the +; symbol names? +; +; PUBLIC @rust_psm_stack_direction@0 +; PUBLIC @rust_psm_stack_pointer@0 +; PUBLIC @rust_psm_replace_stack@12 +; PUBLIC @rust_psm_on_stack@16 + +_TEXT SEGMENT + +; extern "fastcall" fn() -> u8 (%al) +@rust_psm_stack_direction@0 PROC SYSCALL + mov al, 2 + ret +@rust_psm_stack_direction@0 ENDP + +; extern "fastcall" fn() -> *mut u8 (%rax) +@rust_psm_stack_pointer@0 PROC SYSCALL + lea eax, [esp + 4] + ret +@rust_psm_stack_pointer@0 ENDP + +; extern "fastcall" fn(%ecx: usize, %edx: extern "fastcall" fn(usize), +; 4(%esp): *mut u8, 8(%esp): *mut u8) +@rust_psm_replace_stack@16 PROC SYSCALL + mov eax, dword ptr [esp + 8] + mov fs:[08h], eax + mov esp, dword ptr [esp + 4] + mov fs:[04h], esp + jmp edx +@rust_psm_replace_stack@16 ENDP + +; extern "fastcall" fn(%ecx: usize, %edx: usize, 4(%esp): extern "fastcall" fn(usize, usize), +; 8(%esp): *mut u8, 12(%esp): *mut u8) +; +; NB: on Windows for SEH to work at all, the pointers in TIB, thread information block, need to be +; fixed up. Otherwise, it seems that exception mechanism on Windows will not bother looking for +; exception handlers at *all* if they happen to fall outside the are specified in TIB. +; +; This necessitates an API difference from the usual 4-argument signature used elsewhere. +@rust_psm_on_stack@20 PROC SYSCALL + push ebp + mov ebp, esp + + push fs:[0E0Ch] + push fs:[08h] + mov eax, dword ptr [ebp + 4 + 12] + mov dword ptr fs:[08h], eax + mov dword ptr fs:[0E0Ch], eax + push fs:[04h] + mov esp, dword ptr [ebp + 4 + 8] + mov dword ptr fs:[04h], esp + call dword ptr [ebp + 4 + 4] + + lea esp, [ebp - 12] + pop fs:[04h] + pop fs:[08h] + pop fs:[0E0Ch] + pop ebp + ret 12 +@rust_psm_on_stack@20 ENDP + +END diff --git a/vendor/psm/src/arch/x86_windows_gnu.s b/vendor/psm/src/arch/x86_windows_gnu.s new file mode 100644 index 000000000..474d4168a --- /dev/null +++ b/vendor/psm/src/arch/x86_windows_gnu.s @@ -0,0 +1,94 @@ +/* FIXME: this works locally but not on appveyor??!? */ +/* NOTE: fastcall calling convention used on all x86 targets */ +.text + +.def @rust_psm_stack_direction@0 +.scl 2 +.type 32 +.endef +.globl @rust_psm_stack_direction@0 +.p2align 4 +@rust_psm_stack_direction@0: +/* extern "fastcall" fn() -> u8 (%al) */ +.cfi_startproc + movb $2, %al # always descending on x86_64 + retl +.cfi_endproc + + +.def @rust_psm_stack_pointer@0 +.scl 2 +.type 32 +.endef +.globl @rust_psm_stack_pointer@0 +.p2align 4 +@rust_psm_stack_pointer@0: +/* extern "fastcall" fn() -> *mut u8 (%rax) */ +.cfi_startproc + leal 4(%esp), %eax + retl +.cfi_endproc + + +.def @rust_psm_replace_stack@16 +.scl 2 +.type 32 +.endef +.globl @rust_psm_replace_stack@16 +.p2align 4 +@rust_psm_replace_stack@16: +/* extern "fastcall" fn(%ecx: usize, %edx: extern "fastcall" fn(usize), 4(%esp): *mut u8) */ +.cfi_startproc +/* + All we gotta do is set the stack pointer to 4(%esp) & tail-call the callback in %edx + + Note, that the callee expects the stack to be offset by 4 bytes (normally, a return address + would be store there) off the required stack alignment on entry. To offset the stack in such a + way we use the `calll` instruction, however it would also be possible to to use plain `jmpl` but + would require to adjust the stack manually, which cannot be easily done, because the stack + pointer argument is already stored in memory. + */ + movl 8(%esp), %eax + mov %eax, %fs:0x08 + movl 4(%esp), %esp + mov %esp, %fs:0x04 + calll *%edx + ud2 +.cfi_endproc + + +.def @rust_psm_on_stack@16 +.scl 2 +.type 32 +.endef +.globl @rust_psm_on_stack@16 +.p2align 4 +@rust_psm_on_stack@16: +/* extern "fastcall" fn(%ecx: usize, %edx: usize, 4(%esp): extern "fastcall" fn(usize, usize), 8(%esp): *mut u8) */ +.cfi_startproc + pushl %ebp + .cfi_def_cfa %esp, 8 + .cfi_offset %ebp, -8 + pushl %fs:0x04 + .cfi_def_cfa %esp, 12 + pushl %fs:0x08 + .cfi_def_cfa %esp, 16 + movl %esp, %ebp + .cfi_def_cfa_register %ebp + + movl 24(%ebp), %eax + movl %eax, %fs:0x08 + movl 20(%ebp), %esp + movl %esp, %fs:0x04 + calll *16(%ebp) + + movl %ebp, %esp + popl %fs:0x08 + .cfi_def_cfa %esp, 12 + popl %fs:0x04 + .cfi_def_cfa %esp, 8 + popl %ebp + .cfi_def_cfa %esp, 4 + retl $12 +.cfi_endproc + diff --git a/vendor/psm/src/arch/zseries_linux.s b/vendor/psm/src/arch/zseries_linux.s new file mode 100644 index 000000000..e2536a1c9 --- /dev/null +++ b/vendor/psm/src/arch/zseries_linux.s @@ -0,0 +1,75 @@ +/* Implementation of stack swtiching routines for zSeries LINUX ABI. + + This ABI is used by the s390x-unknown-linux-gnu target. + + Documents used: + + * LINUX for zSeries: ELF Application Binary Interface Supplement (1st ed., 2001) (LNUX-1107-01) + * z/Architecture: Principles of Operation (4th ed., 2004) (SA22-7832-03) +*/ + +#include "psm.h" + +.text + + +.globl rust_psm_stack_direction +.p2align 4 +.type rust_psm_stack_direction,@function +rust_psm_stack_direction: +/* extern "C" fn() -> u8 */ +.cfi_startproc + lghi %r2, STACK_DIRECTION_DESCENDING + br %r14 +.rust_psm_stack_direction_end: +.size rust_psm_stack_direction,.rust_psm_stack_direction_end-rust_psm_stack_direction +.cfi_endproc + + +.globl rust_psm_stack_pointer +.p2align 4 +.type rust_psm_stack_pointer,@function +rust_psm_stack_pointer: +/* extern "C" fn() -> *mut u8 */ +.cfi_startproc + la %r2, 0(%r15) + br %r14 +.rust_psm_stack_pointer_end: +.size rust_psm_stack_pointer,.rust_psm_stack_pointer_end-rust_psm_stack_pointer +.cfi_endproc + + +.globl rust_psm_replace_stack +.p2align 4 +.type rust_psm_replace_stack,@function +rust_psm_replace_stack: +/* extern "C" fn(r2: usize, r3: extern "C" fn(usize), r4: *mut u8) */ +.cfi_startproc + /* FIXME: backtrace does not terminate cleanly for some reason */ + lay %r15, -160(%r4) + /* FIXME: this is `basr` instead of `br` purely to remove the backtrace link to the caller */ + basr %r14, %r3 +.rust_psm_replace_stack_end: +.size rust_psm_replace_stack,.rust_psm_replace_stack_end-rust_psm_replace_stack +.cfi_endproc + + +.globl rust_psm_on_stack +.p2align 4 +.type rust_psm_on_stack,@function +rust_psm_on_stack: +/* extern "C" fn(r2: usize, r3: usize, r4: extern "C" fn(usize, usize), r5: *mut u8) */ +.cfi_startproc + stmg %r14, %r15, -16(%r5) + lay %r15, -176(%r5) + .cfi_def_cfa %r15, 176 + .cfi_offset %r14, -16 + .cfi_offset %r15, -8 + basr %r14, %r4 + lmg %r14, %r15, 160(%r15) + .cfi_restore %r14 + .cfi_restore %r15 + br %r14 +.rust_psm_on_stack_end: +.size rust_psm_on_stack,.rust_psm_on_stack_end-rust_psm_on_stack +.cfi_endproc diff --git a/vendor/psm/src/lib.rs b/vendor/psm/src/lib.rs new file mode 100644 index 000000000..61ab9a85b --- /dev/null +++ b/vendor/psm/src/lib.rs @@ -0,0 +1,406 @@ +//! # **P**ortable **S**tack **M**anipulation +//! This crate provides portable functions to control the stack pointer and inspect the properties +//! of the stack. This crate does not attempt to provide safe abstractions to any operations, the +//! only goals are correctness, portability and efficiency (in that exact order). As a consequence +//! most functions you will find in this crate are unsafe. +//! +//! Note, that the stack allocation is left up to the user. Unless you’re writing a safe +//! abstraction over stack manipulation, this is unlikely to be the crate you want. Instead +//! consider one of the safe abstractions over this crate such as `stacker`. Another good place to +//! look at is the crates.io’s reverse dependency list. + +#![allow(unused_macros)] +#![no_std] + +macro_rules! extern_item { + (unsafe $($toks: tt)+) => { + unsafe extern "C" $($toks)+ + }; + ($($toks: tt)+) => { + extern "C" $($toks)+ + }; +} + +// Surprising: turns out subsequent macro_rules! override previous definitions, instead of +// erroring? Convenient for us in this case, though. +#[cfg(target_arch = "x86_64")] +macro_rules! extern_item { + (unsafe $($toks: tt)+) => { + unsafe extern "sysv64" $($toks)+ + }; + ($($toks: tt)+) => { + extern "sysv64" $($toks)+ + }; +} + +#[cfg(target_arch = "x86")] +macro_rules! extern_item { + (unsafe $($toks: tt)+) => { + unsafe extern "fastcall" $($toks)+ + }; + ($($toks: tt)+) => { + extern "fastcall" $($toks)+ + }; +} + +#[cfg(target_arch = "arm")] +macro_rules! extern_item { + (unsafe $($toks: tt)+) => { + unsafe extern "aapcs" $($toks)+ + }; + ($($toks: tt)+) => { + extern "aapcs" $($toks)+ + }; +} + +// NB: this could be nicer across multiple blocks but we cannot do it because of +// https://github.com/rust-lang/rust/issues/65847 +extern_item! { { + #![link(name="psm_s")] + + #[cfg(asm)] + fn rust_psm_stack_direction() -> u8; + #[cfg(asm)] + fn rust_psm_stack_pointer() -> *mut u8; + + #[cfg(all(switchable_stack, not(target_os = "windows")))] + #[link_name="rust_psm_replace_stack"] + fn _rust_psm_replace_stack( + data: usize, + callback: extern_item!(unsafe fn(usize) -> !), + sp: *mut u8 + ) -> !; + #[cfg(all(switchable_stack, not(target_os = "windows")))] + #[link_name="rust_psm_on_stack"] + fn _rust_psm_on_stack( + data: usize, + return_ptr: usize, + callback: extern_item!(unsafe fn(usize, usize)), + sp: *mut u8, + ); + #[cfg(all(switchable_stack, target_os = "windows"))] + fn rust_psm_replace_stack( + data: usize, + callback: extern_item!(unsafe fn(usize) -> !), + sp: *mut u8, + stack_base: *mut u8 + ) -> !; + #[cfg(all(switchable_stack, target_os = "windows"))] + fn rust_psm_on_stack( + data: usize, + return_ptr: usize, + callback: extern_item!(unsafe fn(usize, usize)), + sp: *mut u8, + stack_base: *mut u8 + ); +} } + +#[cfg(all(switchable_stack, not(target_os = "windows")))] +#[inline(always)] +unsafe fn rust_psm_replace_stack( + data: usize, + callback: extern_item!(unsafe fn(usize) -> !), + sp: *mut u8, + _: *mut u8, +) -> ! { + _rust_psm_replace_stack(data, callback, sp) +} + +#[cfg(all(switchable_stack, not(target_os = "windows")))] +#[inline(always)] +unsafe fn rust_psm_on_stack( + data: usize, + return_ptr: usize, + callback: extern_item!(unsafe fn(usize, usize)), + sp: *mut u8, + _: *mut u8, +) { + _rust_psm_on_stack(data, return_ptr, callback, sp) +} + +/// Run the closure on the provided stack. +/// +/// Once the closure completes its execution, the original stack pointer is restored and execution +/// returns to the caller. +/// +/// `base` address must be the low address of the stack memory region, regardless of the stack +/// growth direction. It is not necessary for the whole region `[base; base + size]` to be usable +/// at the time this function called, however it is required that at least the following hold: +/// +/// * Both `base` and `base + size` are aligned up to the target-specific requirements; +/// * Depending on `StackDirection` value for the platform, the end of the stack memory region, +/// which would end up containing the first frame(s), must have sufficient number of pages +/// allocated to execute code until more pages are commited. The other end should contain a guard +/// page (not writable, readable or executable) to ensure Rust’s soundness guarantees. +/// +/// Note, that some or all of these considerations are irrelevant to some applications. For +/// example, Rust’s soundness story relies on all stacks having a guard-page, however if the user +/// is able to guarantee that the memory region used for stack cannot be exceeded, a guard page may +/// end up being an expensive unnecessity. +/// +/// The previous stack may not be deallocated. If an ability to deallocate the old stack is desired +/// consider `replace_stack` instead. +/// +/// # Guidelines +/// +/// Memory regions that are aligned to a single page (usually 4kB) are an extremely portable choice +/// for stacks. +/// +/// Allocate at least 4kB of stack. Some architectures (such as SPARC) consume stack memory +/// significantly faster compared to the more usual architectures such as x86 or ARM. Allocating +/// less than 4kB of memory may make it impossible to commit more pages without overflowing the +/// stack later on. +/// +/// # Unsafety +/// +/// The stack `base` address must be aligned as appropriate for the target. +/// +/// The stack `size` must be a multiple of stack alignment required by target. +/// +/// The `size` must not overflow `isize`. +/// +/// `callback` must not unwind or return control flow by any other means than directly returning. +/// +/// # Examples +/// +/// ``` +/// use std::alloc; +/// const STACK_ALIGN: usize = 4096; +/// const STACK_SIZE: usize = 4096; +/// unsafe { +/// let layout = alloc::Layout::from_size_align(STACK_SIZE, STACK_ALIGN).unwrap(); +/// let new_stack = alloc::alloc(layout); +/// assert!(!new_stack.is_null(), "allocations must succeed!"); +/// let (stack, result) = psm::on_stack(new_stack, STACK_SIZE, || { +/// (psm::stack_pointer(), 4 + 4) +/// }); +/// println!("4 + 4 = {} has been calculated on stack {:p}", result, stack); +/// } +/// ``` +#[cfg(switchable_stack)] +pub unsafe fn on_stack<R, F: FnOnce() -> R>(base: *mut u8, size: usize, callback: F) -> R { + use core::mem::MaybeUninit; + + extern_item! { + unsafe fn with_on_stack<R, F: FnOnce() -> R>(callback_ptr: usize, return_ptr: usize) { + let return_ptr = (*(return_ptr as *mut MaybeUninit<R>)).as_mut_ptr(); + let callback = (*(callback_ptr as *mut MaybeUninit<F>)).as_ptr(); + // Safe to move out from `F`, because closure in is forgotten in `on_stack` and dropping + // only occurs in this callback. + return_ptr.write((callback.read())()); + } + } + let sp = match StackDirection::new() { + StackDirection::Ascending => base, + StackDirection::Descending => base.offset(size as isize), + }; + let mut callback: MaybeUninit<F> = MaybeUninit::new(callback); + let mut return_value: MaybeUninit<R> = MaybeUninit::uninit(); + rust_psm_on_stack( + &mut callback as *mut MaybeUninit<F> as usize, + &mut return_value as *mut MaybeUninit<R> as usize, + with_on_stack::<R, F>, + sp, + base, + ); + return return_value.assume_init(); +} + +/// Run the provided non-terminating computation on an entirely new stack. +/// +/// `base` address must be the low address of the stack memory region, regardless of the stack +/// growth direction. It is not necessary for the whole region `[base; base + size]` to be usable +/// at the time this function called, however it is required that at least the following hold: +/// +/// * Both `base` and `base + size` are aligned up to the target-specific requirements; +/// * Depending on `StackDirection` value for the platform, the end of the stack memory region, +/// which would end up containing the first frame(s), must have sufficient number of pages +/// allocated to execute code until more pages are commited. The other end should contain a guard +/// page (not writable, readable or executable) to ensure Rust’s soundness guarantees. +/// +/// Note, that some or all of these considerations are irrelevant to some applications. For +/// example, Rust’s soundness story relies on all stacks having a guard-page, however if the user +/// is able to guarantee that the memory region used for stack cannot be exceeded, a guard page may +/// end up being an expensive unnecessity. +/// +/// The previous stack is not deallocated and may not be deallocated unless the data on the old +/// stack is not referenced in any way (by e.g. the `callback` closure). +/// +/// On platforms where multiple stack pointers are available, the “current” stack pointer is +/// replaced. +/// +/// # Guidelines +/// +/// Memory regions that are aligned to a single page (usually 4kB) are an extremely portable choice +/// for stacks. +/// +/// Allocate at least 4kB of stack. Some architectures (such as SPARC) consume stack memory +/// significantly faster compared to the more usual architectures such as x86 or ARM. Allocating +/// less than 4kB of memory may make it impossible to commit more pages without overflowing the +/// stack later on. +/// +/// # Unsafety +/// +/// The stack `base` address must be aligned as appropriate for the target. +/// +/// The stack `size` must be a multiple of stack alignment required by target. +/// +/// The `size` must not overflow `isize`. +/// +/// `callback` must not return (not enforced by typesystem currently because `!` is unstable), +/// unwind or otherwise return control flow to any of the previous frames. +#[cfg(switchable_stack)] +pub unsafe fn replace_stack<F: FnOnce()>(base: *mut u8, size: usize, callback: F) -> ! { + extern_item! { unsafe fn with_replaced_stack<F: FnOnce()>(d: usize) -> ! { + // Safe to move out, because the closure is essentially forgotten by + // this being required to never return... + ::core::ptr::read(d as *const F)(); + ::core::hint::unreachable_unchecked(); + } } + let sp = match StackDirection::new() { + StackDirection::Ascending => base, + StackDirection::Descending => base.offset(size as isize), + }; + rust_psm_replace_stack( + &callback as *const F as usize, + with_replaced_stack::<F>, + sp, + base, + ); +} + +/// The direction into which stack grows as stack frames are made. +/// +/// This is a target-specific property that can be obtained at runtime by calling +/// `StackDirection::new()`. +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +pub enum StackDirection { + Ascending = 1, + Descending = 2, +} + +impl StackDirection { + /// Obtain the stack growth direction. + #[cfg(asm)] + pub fn new() -> StackDirection { + const ASC: u8 = StackDirection::Ascending as u8; + const DSC: u8 = StackDirection::Descending as u8; + unsafe { + match rust_psm_stack_direction() { + ASC => StackDirection::Ascending, + DSC => StackDirection::Descending, + _ => ::core::hint::unreachable_unchecked(), + } + } + } +} + +/// Returns current stack pointer. +/// +/// Note, that the stack pointer returned is from the perspective of the caller. From the +/// perspective of `stack_pointer` function the pointer returned is the frame pointer. +/// +/// While it is a goal to minimize the amount of stack used by this function, implementations for +/// some targets may be unable to avoid allocating a stack frame. This makes this function +/// suitable for stack exhaustion detection only in conjunction with sufficient padding. +/// +/// Using `stack_pointer` to check for stack exhaustion is tricky to get right. It is impossible to +/// know the callee’s frame size, therefore such value must be derived some other way. A common +/// approach is to use stack padding (reserve enough stack space for any function to be called) and +/// check against the padded threshold. If padding is chosen incorrectly, a situation similar to +/// one described below may occur: +/// +/// 1. For stack exhaustion check, remaining stack is checked against `stack_pointer` with the +/// padding applied; +/// 2. Callee allocates more stack than was accounted for with padding, and accesses pages outside +/// the stack, invalidating the execution (by e.g. crashing). +#[cfg(asm)] +pub fn stack_pointer() -> *mut u8 { + unsafe { rust_psm_stack_pointer() } +} + +/// Macro that outputs its tokens only if `psm::on_stack` and `psm::replace_stack` are available. +/// +/// # Examples +/// +/// ``` +/// # use psm::psm_stack_manipulation; +/// psm_stack_manipulation! { +/// yes { +/// /* Functions `on_stack` and `replace_stack` are available here */ +/// } +/// no { +/// /* Functions `on_stack` and `replace_stack` are not available here */ +/// } +/// } +/// ``` +#[cfg(switchable_stack)] +#[macro_export] +macro_rules! psm_stack_manipulation { + (yes { $($yes: tt)* } no { $($no: tt)* }) => { $($yes)* }; +} + +/// Macro that outputs its tokens only if `psm::on_stack` and `psm::replace_stack` are available. +/// +/// # Examples +/// +/// ``` +/// # use psm::psm_stack_manipulation; +/// psm_stack_manipulation! { +/// yes { +/// /* Functions `on_stack` and `replace_stack` are available here */ +/// } +/// no { +/// /* Functions `on_stack` and `replace_stack` are not available here */ +/// } +/// } +/// ``` +#[cfg(not(switchable_stack))] +#[macro_export] +macro_rules! psm_stack_manipulation { + (yes { $($yes: tt)* } no { $($no: tt)* }) => { $($no)* }; +} + +/// Macro that outputs its tokens only if `psm::stack_pointer` and `psm::StackDirection::new` are +/// available. +/// +/// # Examples +/// +/// ``` +/// # use psm::psm_stack_information; +/// psm_stack_information! { +/// yes { +/// /* `psm::stack_pointer` and `psm::StackDirection::new` are available here */ +/// } +/// no { +/// /* `psm::stack_pointer` and `psm::StackDirection::new` are not available here */ +/// } +/// } +/// ``` +#[cfg(asm)] +#[macro_export] +macro_rules! psm_stack_information { + (yes { $($yes: tt)* } no { $($no: tt)* }) => { $($yes)* }; +} + +/// Macro that outputs its tokens only if `psm::stack_pointer` and `psm::StackDirection::new` are +/// available. +/// +/// # Examples +/// +/// ``` +/// # use psm::psm_stack_information; +/// psm_stack_information! { +/// yes { +/// /* `psm::stack_pointer` and `psm::StackDirection::new` are available here */ +/// } +/// no { +/// /* `psm::stack_pointer` and `psm::StackDirection::new` are not available here */ +/// } +/// } +/// ``` +#[cfg(not(asm))] +#[macro_export] +macro_rules! psm_stack_information { + (yes { $($yes: tt)* } no { $($no: tt)* }) => { $($no)* }; +} |