1/* Set up a context to call a function. 2 Copyright (C) 2002-2022 Free Software Foundation, Inc. 3 This file is part of the GNU C Library. 4 5 The GNU C Library is free software; you can redistribute it and/or 6 modify it under the terms of the GNU Lesser General Public 7 License as published by the Free Software Foundation; either 8 version 2.1 of the License, or (at your option) any later version. 9 10 The GNU C Library is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 Lesser General Public License for more details. 14 15 You should have received a copy of the GNU Lesser General Public 16 License along with the GNU C Library; if not, see 17 <https://www.gnu.org/licenses/>. */ 18 19#include <sysdep.h> 20#include <shlib-compat.h> 21 22#define __ASSEMBLY__ 23#include <asm/ptrace.h> 24#include "ucontext_i.h" 25 26ENTRY(__makecontext) 27 /* Set up the first 7 args to the function in its registers */ 28 lwz r11,_UC_REGS_PTR(r3) 29 stw r6,_UC_GREGS+(PT_R3*4)(r11) 30 stw r7,_UC_GREGS+(PT_R4*4)(r11) 31 stw r8,_UC_GREGS+(PT_R5*4)(r11) 32 stw r9,_UC_GREGS+(PT_R6*4)(r11) 33 stw r10,_UC_GREGS+(PT_R7*4)(r11) 34 lwz r8,8(r1) 35 lwz r9,12(r1) 36 stw r8,_UC_GREGS+(PT_R8*4)(r11) 37 stw r9,_UC_GREGS+(PT_R9*4)(r11) 38 39 /* Set the NIP to the start of the function */ 40 stw r4,_UC_GREGS+(PT_NIP*4)(r11) 41 42 /* Set the function's r31 to ucp->uc_link for the exitcode below. */ 43 lwz r7,_UC_LINK(r3) 44 stw r7,_UC_GREGS+(PT_R31*4)(r11) 45 46 /* Set the function's LR to point to the exitcode below. */ 47#ifdef PIC 48 mflr r0 49 cfi_register(lr,r0) 50 /* Use this conditional form of branch and link to avoid destroying 51 the cpu link stack used to predict blr return addresses. */ 52 bcl 20,31,1f 531: mflr r6 54 addi r6,r6,L(exitcode)-1b 55 mtlr r0 56 cfi_same_value (lr) 57#else 58 lis r6,L(exitcode)@ha 59 addi r6,r6,L(exitcode)@l 60#endif 61 stw r6,_UC_GREGS+(PT_LNK*4)(r11) 62 63 /* 64 * Set up the stack frame for the function. 65 * If we have more than 5 args to the function (8 args to makecontext), 66 * there will be some arguments on the stack which have to end up 67 * in registers. If there are more than 8 args to the function, 68 * we have to copy (argc - 8) args from our stack to the functions' 69 * stack (and allow space for them in the frame). 70 */ 71 lwz r4,_UC_STACK_SP(r3) 72 lwz r8,_UC_STACK_SIZE(r3) 73 add r4,r4,r8 74 rlwinm r4,r4,0,0,27 /* round down to 16-byte boundary */ 75 addi r7,r4,-16 /* stack frame for fn's caller */ 76 cmpwi r5,8 77 blt 2f /* less than 8 args is easy */ 78 lwz r10,16(r1) 79 stw r10,_UC_GREGS+(PT_R10*4)(r11) 80 beq 2f /* if exactly 8 args */ 81 subi r9,r5,3 82 subi r5,r5,8 83 rlwinm r9,r9,2,0,27 84 subf r7,r9,r4 85 mtctr r5 /* copy the 9th and following args */ 86 addi r6,r1,16 87 addi r8,r7,4 883: lwzu r10,4(r6) 89 stwu r10,4(r8) 90 bdnz 3b 912: stw r7,_UC_GREGS+(PT_R1*4)(r11) 92 li r6,0 93 stw r6,0(r7) 94 95 blr 96 97 cfi_endproc 98 nop 99/* 100 * If the function returns, it comes here. We put ucp->uc_link in 101 * r31, which is a callee-saved register. We have to continue with 102 * the context that r31 points to, or exit if it is 0. 103 */ 104L(exitcode): 105 mr. r3,r31 106 beq 4f 107 bl __setcontext@local 1084: bl HIDDEN_JUMPTARGET(exit) 109 b 4b 110 111 cfi_startproc 112END(__makecontext) 113 114versioned_symbol (libc, __makecontext, makecontext, GLIBC_2_3_4) 115 116#if SHLIB_COMPAT (libc, GLIBC_2_3_3, GLIBC_2_3_4) 117 118 compat_text_section 119ENTRY(__novec_makecontext) 120 /* Set up the first 7 args to the function in its registers */ 121 addi r11,r3,_UC_REG_SPACE 122 stw r11,_UC_REGS_PTR(r3) 123 stw r6,_UC_GREGS+(PT_R3*4)(r11) 124 stw r7,_UC_GREGS+(PT_R4*4)(r11) 125 stw r8,_UC_GREGS+(PT_R5*4)(r11) 126 stw r9,_UC_GREGS+(PT_R6*4)(r11) 127 stw r10,_UC_GREGS+(PT_R7*4)(r11) 128 lwz r8,8(r1) 129 lwz r9,12(r1) 130 stw r8,_UC_GREGS+(PT_R8*4)(r11) 131 stw r9,_UC_GREGS+(PT_R9*4)(r11) 132 133 /* Set the NIP to the start of the function */ 134 stw r4,_UC_GREGS+(PT_NIP*4)(r11) 135 136 /* Set the function's r31 to ucp->uc_link for the exitcode below. */ 137 lwz r7,_UC_LINK(r3) 138 stw r7,_UC_GREGS+(PT_R31*4)(r11) 139 140 /* Set the function's LR to point to the exitcode below. */ 141#ifdef PIC 142 mflr r0 143 cfi_register(lr,r0) 144 /* Use this conditional form of branch and link to avoid destroying 145 the cpu link stack used to predict blr return addresses. */ 146 bcl 20,31,1f 1471: mflr r6 148 addi r6,r6,L(novec_exitcode)-1b 149 mtlr r0 150 cfi_same_value (lr) 151#else 152 lis r6,L(novec_exitcode)@ha 153 addi r6,r6,L(novec_exitcode)@l 154#endif 155 stw r6,_UC_GREGS+(PT_LNK*4)(r11) 156 157 /* 158 * Set up the stack frame for the function. 159 * If we have more than 5 args to the function (8 args to makecontext), 160 * there will be some arguments on the stack which have to end up 161 * in registers. If there are more than 8 args to the function, 162 * we have to copy (argc - 8) args from our stack to the functions' 163 * stack (and allow space for them in the frame). 164 */ 165 lwz r4,_UC_STACK_SP(r3) 166 lwz r8,_UC_STACK_SIZE(r3) 167 add r4,r4,r8 168 rlwinm r4,r4,0,0,27 /* round down to 16-byte boundary */ 169 addi r7,r4,-16 /* stack frame for fn's caller */ 170 cmpwi r5,8 171 blt 2f /* less than 8 args is easy */ 172 lwz r10,16(r1) 173 stw r10,_UC_GREGS+(PT_R10*4)(r11) 174 beq 2f /* if exactly 8 args */ 175 subi r9,r5,3 176 subi r5,r5,8 177 rlwinm r9,r9,2,0,27 178 subf r7,r9,r4 179 mtctr r5 /* copy the 9th and following args */ 180 addi r6,r1,16 181 addi r8,r7,4 1823: lwzu r10,4(r6) 183 stwu r10,4(r8) 184 bdnz 3b 1852: stw r7,_UC_GREGS+(PT_R1*4)(r11) 186 li r6,0 187 stw r6,0(r7) 188 189 blr 190 191 cfi_endproc 192 nop 193/* 194 * If the function returns, it comes here. We put ucp->uc_link in 195 * r31, which is a callee-saved register. We have to continue with 196 * the context that r31 points to, or exit if it is 0. 197 */ 198L(novec_exitcode): 199 mr. r3,r31 200 beq 4f 201 bl __novec_setcontext@local 2024: bl HIDDEN_JUMPTARGET(exit) 203 b 4b 204 205 cfi_startproc 206END(__novec_makecontext) 207 .previous 208 209compat_symbol (libc, __novec_makecontext, makecontext, GLIBC_2_3_3) 210#endif 211 212#if SHLIB_COMPAT (libc, GLIBC_2_1, GLIBC_2_3_3) 213 214#define _ERRNO_H 1 215#include <bits/errno.h> 216 217 compat_text_section 218ENTRY (__makecontext_stub) 219 li r3,ENOSYS 220 b __syscall_error@local 221END (__makecontext_stub) 222 .previous 223 224compat_symbol (libc, __makecontext_stub, makecontext, GLIBC_2_1) 225 226#endif 227