From 922e033fa1464e506c82a0d6980103268f7197cf Mon Sep 17 00:00:00 2001 From: David Seifert Date: Tue, 23 Jan 2024 13:23:29 +0100 Subject: [PATCH 1/6] Fix x32 build on x86-64 --- src/asm/jump_i386_sysv_elf_gas.S | 6 ++++++ src/asm/make_i386_sysv_elf_gas.S | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/src/asm/jump_i386_sysv_elf_gas.S b/src/asm/jump_i386_sysv_elf_gas.S index 47be9e77..ed83717c 100644 --- a/src/asm/jump_i386_sysv_elf_gas.S +++ b/src/asm/jump_i386_sysv_elf_gas.S @@ -24,6 +24,10 @@ * * ****************************************************************************************/ +#ifdef __x86_64__ +#include "jump_x86_64_sysv_elf_gas.S" +#else + .file "jump_i386_sysv_elf_gas.S" .text .globl jump_fcontext @@ -91,3 +95,5 @@ jump_fcontext: /* Mark that we don't need executable stack. */ .section .note.GNU-stack,"",%progbits + +#endif diff --git a/src/asm/make_i386_sysv_elf_gas.S b/src/asm/make_i386_sysv_elf_gas.S index 9261e566..c6e0b365 100644 --- a/src/asm/make_i386_sysv_elf_gas.S +++ b/src/asm/make_i386_sysv_elf_gas.S @@ -24,6 +24,10 @@ * * ****************************************************************************************/ +#ifdef __x86_64__ +#include "make_x86_64_sysv_elf_gas.S" +#else + .file "make_i386_sysv_elf_gas.S" .text .globl make_fcontext @@ -111,3 +115,5 @@ finish: /* Mark that we don't need executable stack. */ .section .note.GNU-stack,"",%progbits + +#endif From a2dd396dd9c6a5c25535796ad7ca2bd7122d31ec Mon Sep 17 00:00:00 2001 From: David Carlier Date: Sun, 4 Feb 2024 08:07:39 +0000 Subject: [PATCH 2/6] fix solaris/illumos build on make/jump assembly directives. on those platforms, albeit being 64 bits, they produce 32 bits binaries by default. --- src/asm/jump_x86_64_sysv_elf_gas.S | 24 +++++++++---- src/asm/make_x86_64_sysv_elf_gas.S | 57 ++++++++++++++++++++++++++---- 2 files changed, 68 insertions(+), 13 deletions(-) diff --git a/src/asm/jump_x86_64_sysv_elf_gas.S b/src/asm/jump_x86_64_sysv_elf_gas.S index 58f0e241..be264bdc 100644 --- a/src/asm/jump_x86_64_sysv_elf_gas.S +++ b/src/asm/jump_x86_64_sysv_elf_gas.S @@ -31,13 +31,16 @@ * * ****************************************************************************************/ -# if defined __CET__ -# include -# define SHSTK_ENABLED (__CET__ & 0x2) -# define BOOST_CONTEXT_SHADOW_STACK (SHSTK_ENABLED && SHADOW_STACK_SYSCALL) +# ifdef __i386__ +# include "jump_i386_sysv_elf_gas.S" # else -# define _CET_ENDBR -# endif +# if defined __CET__ +# include +# define SHSTK_ENABLED (__CET__ & 0x2) +# define BOOST_CONTEXT_SHADOW_STACK (SHSTK_ENABLED && SHADOW_STACK_SYSCALL) +# else +# define _CET_ENDBR +# endif .file "jump_x86_64_sysv_elf_gas.S" .text .globl jump_fcontext @@ -72,6 +75,14 @@ jump_fcontext: movq %rcx, (%rsp) #endif +#if BOOST_CONTEXT_SHADOW_STACK + /* grow the stack to reserve space for shadow stack pointer(SSP) */ + leaq -0x8(%rsp), %rsp + /* read the current SSP and store it */ + rdsspq %rcx + movq %rcx, (%rsp) +# endif + /* store RSP (pointing to context-data) in RAX */ movq %rsp, %rax @@ -140,3 +151,4 @@ jump_fcontext: /* Mark that we don't need executable stack. */ .section .note.GNU-stack,"",%progbits +# endif diff --git a/src/asm/make_x86_64_sysv_elf_gas.S b/src/asm/make_x86_64_sysv_elf_gas.S index 4294398a..b0d0c034 100644 --- a/src/asm/make_x86_64_sysv_elf_gas.S +++ b/src/asm/make_x86_64_sysv_elf_gas.S @@ -31,13 +31,16 @@ * * ****************************************************************************************/ -# if defined __CET__ -# include -# define SHSTK_ENABLED (__CET__ & 0x2) -# define BOOST_CONTEXT_SHADOW_STACK (SHSTK_ENABLED && SHADOW_STACK_SYSCALL) +# ifdef __i386__ +# include "make_i386_sysv_elf_gas.S" # else -# define _CET_ENDBR -# endif +# if defined __CET__ +# include +# define SHSTK_ENABLED (__CET__ & 0x2) +# define BOOST_CONTEXT_SHADOW_STACK (SHSTK_ENABLED && SHADOW_STACK_SYSCALL) +# else +# define _CET_ENDBR +# endif .file "make_x86_64_sysv_elf_gas.S" .text .globl make_fcontext @@ -45,6 +48,7 @@ .align 16 make_fcontext: _CET_ENDBR + #if BOOST_CONTEXT_SHADOW_STACK /* the new shadow stack pointer (SSP) */ movq -0x8(%rdi), %r9 @@ -116,12 +120,50 @@ make_fcontext: movq %r9, (%rax) #endif +#if BOOST_CONTEXT_SHADOW_STACK + /* Populate the shadow stack */ + + /* get original SSP */ + rdsspq %r8 + /* restore new shadow stack */ + rstorssp -0x8(%r9) + /* save the restore token on the original shadow stack */ + saveprevssp + /* push the address of "jmp trampoline" to the new shadow stack */ + /* as well as the stack */ + call 1f + jmp trampoline +1: + /* save address of "jmp trampoline" as return-address */ + /* for context-function */ + pop 0x38(%rax) + /* Get the new SSP. */ + rdsspq %r9 + /* restore original shadow stack */ + rstorssp -0x8(%r8) + /* save the restore token on the new shadow stack. */ + saveprevssp + + /* now the new shadow stack looks like: + base-> +------------------------------+ + | address of "jmp trampoline" | + SSP-> +------------------------------+ + | restore token | + +------------------------------+ + */ + + /* reserve space for the new SSP */ + leaq -0x8(%rax), %rax + /* save the new SSP to this fcontext */ + movq %r9, (%rax) +#endif + ret /* return pointer to context-data */ trampoline: - _CET_ENDBR /* store return address on stack */ /* fix stack alignment */ + _CET_ENDBR #if BOOST_CONTEXT_SHADOW_STACK /* save address of "jmp *%rbp" as return-address */ /* on stack and shadow stack */ @@ -145,3 +187,4 @@ finish: /* Mark that we don't need executable stack. */ .section .note.GNU-stack,"",%progbits +# endif From 22be4b157046b78e6bb9648c47b724f96ba9ab48 Mon Sep 17 00:00:00 2001 From: Claudio Jeker Date: Tue, 13 Feb 2024 10:57:26 +0100 Subject: [PATCH 3/6] Add the BOOST_CONTEXT_USE_MAP_STACK logic to test_fcontext.cpp Without this test_fcontext.cpp fails on OpenBSD with a not-on-stack OS error. --- test/test_fcontext.cpp | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/test/test_fcontext.cpp b/test/test_fcontext.cpp index 51732426..6bbd9ed6 100644 --- a/test/test_fcontext.cpp +++ b/test/test_fcontext.cpp @@ -23,6 +23,12 @@ #include #include +#if defined(BOOST_CONTEXT_USE_MAP_STACK) +extern "C" { +#include +} +#endif + #define BOOST_CHECK(x) BOOST_TEST(x) #define BOOST_CHECK_EQUAL(a, b) BOOST_TEST_EQ(a, b) @@ -44,8 +50,17 @@ class simple_stack_allocator BOOST_ASSERT( minimum_stacksize() <= size); BOOST_ASSERT( maximum_stacksize() >= size); - void * limit = malloc( size); - if ( ! limit) throw std::bad_alloc(); +#if defined(BOOST_CONTEXT_USE_MAP_STACK) + void * limit = ::mmap( 0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON | MAP_STACK, -1, 0); + if ( limit == MAP_FAILED) { + throw std::bad_alloc(); + } +#else + void * limit = std::malloc( size); + if ( ! limit) { + throw std::bad_alloc(); + } +#endif return static_cast< char * >( limit) + size; } @@ -57,7 +72,11 @@ class simple_stack_allocator BOOST_ASSERT( maximum_stacksize() >= size); void * limit = static_cast< char * >( vp) - size; +#if defined(BOOST_CONTEXT_USE_MAP_STACK) + ::munmap( vp, size); +#else free( limit); +#endif } }; From 17945a28a21d3e17c7ff6d44ce2ee021121d54d4 Mon Sep 17 00:00:00 2001 From: Claudio Jeker Date: Tue, 13 Feb 2024 11:04:27 +0100 Subject: [PATCH 4/6] Implement the fcontext asm for sparc64 This implements the required asm functions for sparc64_sysv_elf and was tested on an OpenBSD/sparc64 system. Jump_fcontext uses an extra C call frame to store the frame-pointer and return address. Because of this the code is simply a save (to new reg window), then forcing a window flush and finally switch stack and restore from there. Since jump_fcontext() uses a register window and stack frame, make_fcontext() reserves two call frames on the stack (one for jump_fcontext() and the other for the callback function). OpenBSD/sparc64 uses stackghost which prevents userland from overriding the return-address on the stack. Because of this make_fcontext() uses an extra trampoline to implement the _exit(0) call if the callback returns. All tests pass with this on OpenBSD/sparc64 (also the tests for fiber, coroutine and coroutine2). --- build/Jamfile.v2 | 24 ++++++++++ src/asm/jump_sparc64_sysv_elf_gas.S | 51 +++++++++++++++++++++ src/asm/make_sparc64_sysv_elf_gas.S | 68 ++++++++++++++++++++++++++++ src/asm/ontop_sparc64_sysv_elf_gas.S | 50 ++++++++++++++++++++ 4 files changed, 193 insertions(+) create mode 100644 src/asm/jump_sparc64_sysv_elf_gas.S create mode 100644 src/asm/make_sparc64_sysv_elf_gas.S create mode 100644 src/asm/ontop_sparc64_sysv_elf_gas.S diff --git a/build/Jamfile.v2 b/build/Jamfile.v2 index c07847ab..00bef6eb 100644 --- a/build/Jamfile.v2 +++ b/build/Jamfile.v2 @@ -508,6 +508,30 @@ alias asm_sources gcc ; +# SPARC64 +# SPARC64/SYSV/ELF +alias asm_sources + : asm/make_sparc64_sysv_elf_gas.S + asm/jump_sparc64_sysv_elf_gas.S + asm/ontop_sparc64_sysv_elf_gas.S + : sysv + 64 + sparc + elf + clang + ; + +alias asm_sources + : asm/make_sparc64_sysv_elf_gas.S + asm/jump_sparc64_sysv_elf_gas.S + asm/ontop_sparc64_sysv_elf_gas.S + : sysv + 64 + sparc + elf + gcc + ; + # S390X # S390X/SYSV/ELF alias asm_sources diff --git a/src/asm/jump_sparc64_sysv_elf_gas.S b/src/asm/jump_sparc64_sysv_elf_gas.S new file mode 100644 index 00000000..61101fb1 --- /dev/null +++ b/src/asm/jump_sparc64_sysv_elf_gas.S @@ -0,0 +1,51 @@ +/* + Copyright Claudio Jeker 2024 + Distributed under the Boost Software License, Version 1.0. + (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt) +*/ + +/* + * typedef void* fcontext_t; + * + * struct transfer_t { + * fcontext_t fctx; + * void * data; + * }; + * + * transfer_t jump_fcontext(fcontext_t const to, void *vp); + */ +#define CC64FSZ 176 +#define BIAS 2047 +#define SP 128 +#define I7 136 + +.file "jump_sparc64_sysv_elf_gas.S" +.text +.align 4 +.global jump_fcontext +.type jump_fcontext, %function +jump_fcontext: + # prepare stack + save %sp, -CC64FSZ, %sp + + # store framepointer and return address in slots reserved + # for arguments + stx %fp, [%sp + BIAS + SP] + stx %i7, [%sp + BIAS + I7] + mov %sp, %o0 + # force flush register windows to stack and with that save context + flushw + # get SP (pointing to new context-data) from %i0 param + mov %i0, %sp + # load framepointer and return address from context + ldx [%sp + BIAS + SP], %fp + ldx [%sp + BIAS + I7], %i7 + + ret + restore %o0, %g0, %o0 + # restore old %sp (pointing to old context-data) in %o0 + # *data stored in %o1 was not modified +.size jump_fcontext,.-jump_fcontext +# Mark that we don't need executable stack. +.section .note.GNU-stack,"",%progbits diff --git a/src/asm/make_sparc64_sysv_elf_gas.S b/src/asm/make_sparc64_sysv_elf_gas.S new file mode 100644 index 00000000..3e7ee809 --- /dev/null +++ b/src/asm/make_sparc64_sysv_elf_gas.S @@ -0,0 +1,68 @@ +/* + Copyright Claudio Jeker 2024 + Distributed under the Boost Software License, Version 1.0. + (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt) +*/ + +/* + * fcontext_t *make_fcontext(void *sp, size_t size, void (*fn)(transfer_t)); + */ +#define CC64FSZ 176 +#define BIAS 2047 +#define FP 112 +#define SP 128 +#define I7 136 + +.file "make_sparc64_sysv_elf_gas.S" +.text +.align 4 +.global make_fcontext +.type make_fcontext, %function +make_fcontext: + save %sp, -CC64FSZ, %sp + + # shift address in %i0 (allocated stack) to lower 16 byte boundary + and %i0, -0xf, %i0 + + # reserve space for two frames on the stack + # the first frame is for the call the second one holds the data + # for jump_fcontext + sub %i0, 2 * CC64FSZ, %i0 + + # third argument of make_fcontext() is the context-function to call + # store it in the first stack frame, also clear %fp there to indicate + # the end of the stack. + stx %i2, [%i0 + CC64FSZ + I7] + stx %g0, [%i0 + CC64FSZ + FP] + + # On OpenBSD stackghost prevents overriding the return address on + # a stack frame. So this code uses an extra trampoline to load + # to call the context-function and then do the _exit(0) dance. + # Extract the full address of the trampoline via pc relative addressing +1: + rd %pc, %l0 + add %l0, (trampoline - 1b - 8), %l0 + stx %l0, [%i0 + I7] + + # Save framepointer to first stack frame but first substract the BIAS + add %i0, CC64FSZ - BIAS, %l0 + stx %l0, [%i0 + SP] + + # Return context-data which is also includes the BIAS + ret + restore %i0, -BIAS, %o0 + +trampoline: + ldx [%sp + BIAS + I7], %l0 + + # no need to setup transfer_t, already in %o0 and %o1 + jmpl %l0, %o7 + nop + + call _exit + clr %o0 + unimp +.size make_fcontext,.-make_fcontext +# Mark that we don't need executable stack. +.section .note.GNU-stack,"",%progbits diff --git a/src/asm/ontop_sparc64_sysv_elf_gas.S b/src/asm/ontop_sparc64_sysv_elf_gas.S new file mode 100644 index 00000000..2fcdb891 --- /dev/null +++ b/src/asm/ontop_sparc64_sysv_elf_gas.S @@ -0,0 +1,50 @@ +/* + Copyright Claudio Jeker 2024 + Distributed under the Boost Software License, Version 1.0. + (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt) +*/ + +/* + * transfer_t ontop_fcontext(fcontext_t const to, void *vp, transfer_t (*fn)(transfer_t)); + */ +#define CC64FSZ 176 +#define BIAS 2047 +#define SP 128 +#define I7 136 + +.file "ontop_sparc64_sysv_elf_gas.S" +.text +.align 4 +.global ontop_fcontext +.type ontop_fcontext, %function +ontop_fcontext: + # prepare stack + save %sp, -CC64FSZ, %sp + + # store framepointer and return address in slots reserved + # for arguments + stx %fp, [%sp + BIAS + SP] + stx %i7, [%sp + BIAS + I7] + mov %sp, %o0 + # force flush register windows to stack and with that save context + flushw + # get SP (pointing to new context-data) from %i0 param + mov %i0, %sp + # load framepointer and return address from context + ldx [%sp + BIAS + SP], %fp + ldx [%sp + BIAS + I7], %i7 + + # ontop_fcontext requires to directly call a function on top of the + # current frame so restore register window before doing the jump + # to the context function which then is in %o2. Do not clobber + # %o7 in the jump so that (*fn)() returns to that address. + restore %o0, %g0, %o0 + # restore old %sp (pointing to old context-data) in %o0 + # *data stored in %o1 was not modified + + jmpl %o2, %g0 + nop +.size jump_fcontext,.-jump_fcontext +# Mark that we don't need executable stack. +.section .note.GNU-stack,"",%progbits From 99be0a678d63374877311f31a10562c5d2fb169c Mon Sep 17 00:00:00 2001 From: Oliver Kowalke Date: Sun, 10 Mar 2024 20:07:00 +0100 Subject: [PATCH 5/6] support gcc for ARM64 on mac OS X - #255 --- build/Jamfile.v2 | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/build/Jamfile.v2 b/build/Jamfile.v2 index c07847ab..a2689686 100644 --- a/build/Jamfile.v2 +++ b/build/Jamfile.v2 @@ -230,6 +230,17 @@ alias asm_sources darwin ; +alias asm_sources + : asm/make_arm64_aapcs_macho_gas.S + asm/jump_arm64_aapcs_macho_gas.S + asm/ontop_arm64_aapcs_macho_gas.S + : aapcs + 64 + arm + mach-o + gcc + ; + # ARM64/AAPCS/PE alias asm_sources : asm/make_arm64_aapcs_pe_armasm.asm From d811245d08fe575f68fb0743c6c97bb19268b3fd Mon Sep 17 00:00:00 2001 From: Oliver Kowalke Date: Sun, 10 Mar 2024 20:20:54 +0100 Subject: [PATCH 6/6] update documentation --- doc/architectures.qbk | 2 +- doc/stack.qbk | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/architectures.qbk b/doc/architectures.qbk index 8cd33eae..b17e1f22 100644 --- a/doc/architectures.qbk +++ b/doc/architectures.qbk @@ -21,7 +21,7 @@ architectures: [[ppc64] [SYSV|ELF|XCOFF] [-] [SYSV|MACH-O] [-]] [[riscv64] [SYSV|ELF] [-] [SYSV] [-]] [[s390x] [SYSV|ELF] [-] [-] [-]] - [[sparc] [-] [-] [-] [-]] + [[sparc64] [SYSV|ELF] [-] [-] [-]] [[x86_64] [SYSV,X32|ELF] [MS|PE] [SYSV|MACH-O] [-]] ] diff --git a/doc/stack.qbk b/doc/stack.qbk index 4445a807..171a7969 100644 --- a/doc/stack.qbk +++ b/doc/stack.qbk @@ -291,7 +291,7 @@ a stack.]] [variablelist [[Returns:] [Returns a default stack size, which may be platform specific. If the stack is unbounded then the present implementation returns the maximum of -`64 kB` and `minimum_size()`.]] +`128 kB` and `minimum_size()`.]] [[Throws:] [Nothing.]] ]