File: makecontext.S

package info (click to toggle)
glibc 2.36-8
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 297,608 kB
  • sloc: ansic: 1,054,210; asm: 325,317; makefile: 14,967; python: 12,603; sh: 10,817; cpp: 5,685; awk: 1,883; perl: 518; yacc: 292; pascal: 182; sed: 39
file content (146 lines) | stat: -rw-r--r-- 3,697 bytes parent folder | download | duplicates (31)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
/* makecontext() for FreeBSD/amd64.
   Copyright (C) 2006 Free Software Foundation, Inc.
   This file is part of the GNU C Library.
   Contributed by Petr Salinger, 2006.

   The GNU C Library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 2.1 of the License, or (at your option) any later version.

   The GNU C Library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public
   License along with the GNU C Library; if not, write to the Free
   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
   02111-1307 USA.  */

#include <sysdep.h>
#include <ucontext_i.h>

/*
   void makecontext(ucontext_t *ucp, void *func(), int argc, ...);


   input parameters:

   rdi		ucp
   rsi		func
   edx		argc
   rcx		arg1	-> ucp.rdi
   r8		arg2	-> ucp.rsi
   r9		arg3	-> ucp.rdx
    8(%rsp)	arg4	-> ucp.rcx
   16(%rsp)	arg5	-> ucp.r8
   24(%rsp)	arg6	-> ucp.r9
   i*8+24(%rsp) arg(6+i)-> future stack

*/

ENTRY(__makecontext)

	/* Compute the address of the stack.
	   The information comes from us_stack element. */
	movq	oSS_SP(%rdi), %rax
	addq	oSS_SIZE(%rdi), %rax

	/* Put start addr into ucp */
	movq	%rsi, oRIP(%rdi)

	/* properly align future stack */
	andq $-16, %rax
	subq   $8, %rax

	/* Put the next context into preserved ucp.rbx
	   (from the uc_link element).  */
	movq	oLINK(%rdi), %rsi
	movq	%rsi, oRBX(%rdi)

	/* save future registers arguments */

	orl %edx, %edx
	jz L(param_done)

	decl %edx
	movq %rcx, oRDI(%rdi)
	jz L(param_done)

	decl %edx
	movq %r8,  oRSI(%rdi)
	jz L(param_done)

	decl %edx
	movq %r9,  oRDX(%rdi)
	jz L(param_done)

	movq 8(%rsp), %rsi
	decl %edx
	movq %rsi, oRCX(%rdi)
	jz L(param_done)

	movq 16(%rsp), %rcx
	decl %edx
	movq %rcx, oR8(%rdi)
	jz L(param_done)

	movq 24(%rsp), %rsi
	decl %edx
	movq %rsi, oR9(%rdi)
	jz L(param_done)

	/* we have to copy some arguments also on the future stack */
	movl %edx, %ecx
	negq %rdx
	leaq -16(%rax,%rdx,8), %rax /* we a litle bit waste stack space */
	orq  $8, %rax

1:	movq 24(%rsp,%rcx,8), %rsi
	movq %rsi,(%rax,%rcx,8)
	loop 1b

L(param_done):

	/* Store the future stack pointer and chain helper code. */
	leaq	L(exitcode)(%rip), %rdx
	movq	%rax, oRSP(%rdi)
	movq	%rdx, (%rax)

	/* 'makecontext' returns no value.  */
	ret

/***************************************************************************/

	/* This is the helper code which gets called if a function which
	   is registered with 'makecontext' returns.  In this case we
	   have to install the context listed in the uc_link element of
	   the context 'makecontext' manipulated at the time of the
	   'makecontext' call.  If the pointer is NULL the process must
	   terminate.  */

L(exitcode):
	/* we don't bother with extra arguments left on the stack
		- more than 6 arguments is rare
		- setcontext changes stacks immediately
		- exit will call _exit in near future
	*/

	movq %rbx, %rdi		/* argument for either syscall */
	testq %rbx, %rbx	/* If it is zero exit.  */
	jz 2f

	call	JUMPTARGET(__setcontext)
	/* If this returns (which can happen if the syscall fails) we'll
	   exit the program with the return error value (-1).  */

	movq %rax, %rdi
2:	call	HIDDEN_JUMPTARGET(exit)
	/* The 'exit' call should never return.  In case it does cause
	   the process to terminate.  */
	hlt
END(__makecontext)

weak_alias(__makecontext, makecontext)