[Info-vax] New PHP kits available (and a programming question)

Mark Berryman mark at theberrymans.com
Thu Jul 13 13:16:10 EDT 2023


On 7/10/23 2:20 PM, John Reagan wrote:
> On Monday, July 10, 2023 at 1:47:58 PM UTC-4, Mark Berryman wrote:
>> .
 >> .
 >> .
>> While I'm waiting for the answers, if anyone knows how I can
>> save/restore execution context and jump to a saved PC location, I would
>> appreciate any hints. I had hoped to use the various *INVO* functions
>> for this but, while I have found routines that will save the current
>> context, I haven't found any that will load the contents of an INVO
>> block back into the registers.
>>
>> Also, what languages have access to all of the registers?
>>
>> Mark Berryman
> Look at SYS$GOTO_UNWIND_64.  It should be able to put all the registers back and jump to a PC.
> 
> The trick is "which PC". Pascal uses it for non-local GOTOs and C uses it for setjmp()/longjmp().
> It takes an invo-handle and a target-PC.  The target-PC needs to be a routine or a label that the
> optimizer treats special (not to optimize things across it).
> 
> For C, setjmp() saves a bunch of stuff from the ICB, longjmp() actually uses a special
> routine inside the CRTL as the target for the SYS$GOTO_UNWIND_64 call.  It gets passed
> the jmp-buf which has the actual destination back in setjmp().  It restores some registers
> and does an indirect jmp back to the saved pc inside the jmp-buf.

It looks like SYS$GOTO_UNWIND_64 will do the trick.  Sadly, I have to 
admit that I got lost trying to understand what the boost code does vs. 
what VMS wants (especially in regards to register usage).  I am asking 
for help in this regard.

There are two functions involved here.  They are defined as follows:

extern void *make_fcontext(void *sp, size_t size, void 
(*fn)(boost_context_data));

extern ZEND_INDIRECT_RETURN boost_context_data jump_fcontext(void *to, 
zend_fiber_transfer *transfer);

typedef struct {
         void *handle;
         zend_fiber_transfer *transfer;
} boost_context_data;

typedef struct _zend_fiber_transfer {
         /* Fiber that will be switched to / has resumed us. */
         zend_fiber_context *context;

         /* Value to that should be send to (or was received from) a 
fiber. */
         zval value;

         /* Bitmask of flags defined in enum zend_fiber_transfer_flag. */
         uint8_t flags;
} zend_fiber_transfer;

struct _zend_fiber_context {
         /* Pointer to boost.context or ucontext_t data. */
         void *handle;

         /* Pointer that identifies the fiber type. */
         void *kind;

         /* Entrypoint function of the fiber. */
         zend_fiber_coroutine function;

         /* Assigned C stack. */
         zend_fiber_stack *stack;

         /* Fiber status. */
         zend_fiber_status status;

         /* Reserved for extensions */
         void *reserved[ZEND_MAX_RESERVED_RESOURCES];
};

typedef struct _zend_fiber_context zend_fiber_context;

And these are the two routines.

-----------------------------------------------------------
/*
             Copyright Oliver Kowalke 2009.
    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)
*/

/****************************************************************************************
  * 
                 *
  * 
---------------------------------------------------------------------------------- 
  *
  *  |    0    |    1    |    2    |    3    |    4     |    5    |    6 
    |    7    |  *
  * 
---------------------------------------------------------------------------------- 
  *
  *  |   0x0   |   0x4   |   0x8   |   0xc   |   0x10   |   0x14  | 
0x18  |   0x1c  |  *
  * 
---------------------------------------------------------------------------------- 
  *
  *  | fc_mxcsr|fc_x87_cw|        R12        |         R13        | 
   R14        |  *
  * 
---------------------------------------------------------------------------------- 
  *
  * 
---------------------------------------------------------------------------------- 
  *
  *  |    8    |    9    |   10    |   11    |    12    |    13   | 
14   |    15   |  *
  * 
---------------------------------------------------------------------------------- 
  *
  *  |   0x20  |   0x24  |   0x28  |  0x2c   |   0x30   |   0x34  | 
0x38  |   0x3c  |  *
  * 
---------------------------------------------------------------------------------- 
  *
  *  |        R15        |        RBX        |         RBP        | 
   RIP        |  *
  * 
---------------------------------------------------------------------------------- 
  *
  * 
                 *
 
****************************************************************************************/

# if defined __CET__
#  include <cet.h>
# else
#  define _CET_ENDBR
# endif
.file "make_x86_64_sysv_elf_gas.S"
.text
.globl make_fcontext
.type make_fcontext, at function
.align 16
make_fcontext:
     /* first arg of make_fcontext() == top of context-stack */
     movq  %rdi, %rax

     /* shift address in RAX to lower 16 byte boundary */
     andq  $-16, %rax

     /* reserve space for context-data on context-stack */
     /* on context-function entry: (RSP -0x8) % 16 == 0 */
     leaq  -0x40(%rax), %rax

     /* third arg of make_fcontext() == address of context-function */
     /* stored in RBX */
     movq  %rdx, 0x28(%rax)

     /* save MMX control- and status-word */
     stmxcsr  (%rax)
     /* save x87 control-word */
     fnstcw   0x4(%rax)

     /* compute abs address of label trampoline */
     leaq  trampoline(%rip), %rcx
     /* save address of trampoline as return-address for context-function */
     /* will be entered after calling jump_fcontext() first time */
     movq  %rcx, 0x38(%rax)

     /* compute abs address of label finish */
     leaq  finish(%rip), %rcx
     /* save address of finish as return-address for context-function */
     /* will be entered after context-function returns */
     movq  %rcx, 0x30(%rax)

     ret /* return pointer to context-data */

trampoline:
     /* store return address on stack */
     /* fix stack alignment */
     push %rbp
     /* jump to context-function */
     jmp *%rbx

finish:
     /* exit code is zero */
     xorq  %rdi, %rdi
     /* exit application */
/*    call  _exit at PLT */
     hlt
.size make_fcontext,.-make_fcontext

/* Mark that we don't need executable stack. */
.section .note.GNU-stack,"",%progbits

------------------------------------------------------------

/*
             Copyright Oliver Kowalke 2009.
    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)
*/

/****************************************************************************************
  * 
                 *
  * 
---------------------------------------------------------------------------------- 
  *
  *  |    0    |    1    |    2    |    3    |    4     |    5    |    6 
    |    7    |  *
  * 
---------------------------------------------------------------------------------- 
  *
  *  |   0x0   |   0x4   |   0x8   |   0xc   |   0x10   |   0x14  | 
0x18  |   0x1c  |  *
  * 
---------------------------------------------------------------------------------- 
  *
  *  | fc_mxcsr|fc_x87_cw|        R12        |         R13        | 
   R14        |  *
  * 
---------------------------------------------------------------------------------- 
  *
  * 
---------------------------------------------------------------------------------- 
  *
  *  |    8    |    9    |   10    |   11    |    12    |    13   | 
14   |    15   |  *
  * 
---------------------------------------------------------------------------------- 
  *
  *  |   0x20  |   0x24  |   0x28  |  0x2c   |   0x30   |   0x34  | 
0x38  |   0x3c  |  *
  * 
---------------------------------------------------------------------------------- 
  *
  *  |        R15        |        RBX        |         RBP        | 
   RIP        |  *
  * 
---------------------------------------------------------------------------------- 
  *
  * 
                 *
 
****************************************************************************************/

# if defined __CET__
#  include <cet.h>
# else
#  define _CET_ENDBR
# endif
.file "jump_x86_64_sysv_elf_gas.S"
.text
.globl jump_fcontext
.type jump_fcontext, at function
.align 16
jump_fcontext:
     leaq  -0x38(%rsp), %rsp /* prepare stack */

#if !defined(BOOST_USE_TSX)
     stmxcsr  (%rsp)     /* save MMX control- and status-word */
     fnstcw   0x4(%rsp)  /* save x87 control-word */
#endif

     movq  %r12, 0x8(%rsp)  /* save R12 */
     movq  %r13, 0x10(%rsp)  /* save R13 */
     movq  %r14, 0x18(%rsp)  /* save R14 */
     movq  %r15, 0x20(%rsp)  /* save R15 */
     movq  %rbx, 0x28(%rsp)  /* save RBX */
     movq  %rbp, 0x30(%rsp)  /* save RBP */

     /* store RSP (pointing to context-data) in RAX */
     movq  %rsp, %rax

     /* restore RSP (pointing to context-data) from RDI */
     movq  %rdi, %rsp

     movq  0x38(%rsp), %r8  /* restore return-address */

#if !defined(BOOST_USE_TSX)
     ldmxcsr  (%rsp)     /* restore MMX control- and status-word */
     fldcw    0x4(%rsp)  /* restore x87 control-word */
#endif

     movq  0x8(%rsp), %r12  /* restore R12 */
     movq  0x10(%rsp), %r13  /* restore R13 */
     movq  0x18(%rsp), %r14  /* restore R14 */
     movq  0x20(%rsp), %r15  /* restore R15 */
     movq  0x28(%rsp), %rbx  /* restore RBX */
     movq  0x30(%rsp), %rbp  /* restore RBP */

     leaq  0x40(%rsp), %rsp /* prepare stack */

     /* return transfer_t from jump */
#if !defined(_ILP32)
     /* RAX == fctx, RDX == data */
     movq  %rsi, %rdx
#else
     /* RAX == data:fctx */
     salq  $32, %rsi
     orq   %rsi, %rax
#endif
     /* pass transfer_t as first arg in context function */
#if !defined(_ILP32)
     /* RDI == fctx, RSI == data */
#else
     /* RDI == data:fctx */
#endif
     movq  %rax, %rdi

     /* indirect jump to context */
     jmp  *%r8
.size jump_fcontext,.-jump_fcontext

/* Mark that we don't need executable stack.  */
.section .note.GNU-stack,"",%progbits

I would greatly appreciate it if anyone is able to take the time to look 
at this.

Mark Berryman









More information about the Info-vax mailing list