(root)/
glibc-2.38/
sysdeps/
unix/
sysv/
linux/
aarch64/
makecontext.c
       1  /* Create new context.
       2     Copyright (C) 2002-2023 Free Software Foundation, Inc.
       3  
       4     This file is part of the GNU C Library.
       5  
       6     The GNU C Library is free software; you can redistribute it and/or
       7     modify it under the terms of the GNU Lesser General Public
       8     License as published by the Free Software Foundation; either
       9     version 2.1 of the License, or (at your option) any later version.
      10  
      11     The GNU C Library is distributed in the hope that it will be useful,
      12     but WITHOUT ANY WARRANTY; without even the implied warranty of
      13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14     Lesser General Public License for more details.
      15  
      16     You should have received a copy of the GNU Lesser General Public
      17     License along with the GNU C Library; if not, see
      18     <https://www.gnu.org/licenses/>.  */
      19  
      20  #include <sysdep.h>
      21  #include <stdarg.h>
      22  #include <stdint.h>
      23  #include <ucontext.h>
      24  
      25  
      26  /* makecontext sets up a stack and the registers for the
      27     user context.  The stack looks like this:
      28  
      29                 +-----------------------+
      30  	       | padding as required   |
      31                 +-----------------------+
      32      sp ->      | parameter 7-n         |
      33                 +-----------------------+
      34  
      35     The registers are set up like this:
      36       %x0 .. %x7: parameter 1 to 8
      37       %x19   : uc_link
      38       %sp    : stack pointer.
      39  */
      40  
      41  void
      42  __makecontext (ucontext_t *ucp, void (*func) (void), int argc, ...)
      43  {
      44    extern void __startcontext (void);
      45    uint64_t *sp;
      46    va_list ap;
      47    int i;
      48  
      49    sp = (uint64_t *)
      50      ((uintptr_t) ucp->uc_stack.ss_sp + ucp->uc_stack.ss_size);
      51  
      52    /* Allocate stack arguments.  */
      53    sp -= argc < 8 ? 0 : argc - 8;
      54  
      55    /* Keep the stack aligned.  */
      56    sp = (uint64_t *) (((uintptr_t) sp) & -16L);
      57  
      58    ucp->uc_mcontext.regs[19] = (uintptr_t) ucp->uc_link;
      59    ucp->uc_mcontext.sp = (uintptr_t) sp;
      60    ucp->uc_mcontext.pc = (uintptr_t) func;
      61    ucp->uc_mcontext.regs[29] = (uintptr_t) 0;
      62    ucp->uc_mcontext.regs[30] = (uintptr_t) &__startcontext;
      63  
      64    va_start (ap, argc);
      65    for (i = 0; i < argc; ++i)
      66      if (i < 8)
      67        ucp->uc_mcontext.regs[i] = va_arg (ap, uint64_t);
      68      else
      69        sp[i - 8] = va_arg (ap, uint64_t);
      70  
      71    va_end (ap);
      72  }
      73  
      74  weak_alias (__makecontext, makecontext)