Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/lib/libc/amd64/gen/makecontext.c
39492 views
1
/*-
2
* SPDX-License-Identifier: BSD-2-Clause
3
*
4
* Copyright (c) 2003 Marcel Moolenaar
5
* All rights reserved.
6
*
7
* Redistribution and use in source and binary forms, with or without
8
* modification, are permitted provided that the following conditions
9
* are met:
10
*
11
* 1. Redistributions of source code must retain the above copyright
12
* notice, this list of conditions and the following disclaimer.
13
* 2. Redistributions in binary form must reproduce the above copyright
14
* notice, this list of conditions and the following disclaimer in the
15
* documentation and/or other materials provided with the distribution.
16
*
17
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
*/
28
29
#include <sys/types.h>
30
#include <sys/ucontext.h>
31
#include <stdarg.h>
32
#include <stdlib.h>
33
34
typedef void (*func_t)(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t,
35
uint64_t);
36
37
/* Prototypes */
38
static void makectx_wrapper(ucontext_t *ucp, func_t func, uint64_t *args);
39
40
__weak_reference(__makecontext, makecontext);
41
42
void
43
__makecontext(ucontext_t *ucp, void (*start)(void), int argc, ...)
44
{
45
uint64_t *args;
46
uint64_t *sp;
47
va_list ap;
48
int i;
49
50
/* A valid context is required. */
51
if ((ucp == NULL) || (ucp->uc_mcontext.mc_len != sizeof(mcontext_t)))
52
return;
53
else if ((argc < 0) || (argc > 6) || (ucp->uc_stack.ss_sp == NULL) ||
54
(ucp->uc_stack.ss_size < MINSIGSTKSZ)) {
55
/*
56
* This should really return -1 with errno set to ENOMEM
57
* or something, but the spec says that makecontext is
58
* a void function. At least make sure that the context
59
* isn't valid so it can't be used without an error.
60
*/
61
ucp->uc_mcontext.mc_len = 0;
62
return;
63
}
64
65
/* Align the stack to 16 bytes. */
66
sp = (uint64_t *)(ucp->uc_stack.ss_sp + ucp->uc_stack.ss_size);
67
sp = (uint64_t *)((uint64_t)sp & ~15UL);
68
69
/* Allocate space for a maximum of 6 arguments on the stack. */
70
args = sp - 6;
71
72
/*
73
* Account for arguments on stack and do the funky C entry alignment.
74
* This means that we need an 8-byte-odd alignment since the ABI expects
75
* the return address to be pushed, thus breaking the 16 byte alignment.
76
*/
77
sp -= 7;
78
79
/* Add the arguments: */
80
va_start(ap, argc);
81
for (i = 0; i < argc; i++)
82
args[i] = va_arg(ap, uint64_t);
83
va_end(ap);
84
for (i = argc; i < 6; i++)
85
args[i] = 0;
86
87
ucp->uc_mcontext.mc_rdi = (register_t)ucp;
88
ucp->uc_mcontext.mc_rsi = (register_t)start;
89
ucp->uc_mcontext.mc_rdx = (register_t)args;
90
ucp->uc_mcontext.mc_rbp = 0;
91
ucp->uc_mcontext.mc_rbx = (register_t)sp;
92
ucp->uc_mcontext.mc_rsp = (register_t)sp;
93
ucp->uc_mcontext.mc_rip = (register_t)makectx_wrapper;
94
}
95
96
static void
97
makectx_wrapper(ucontext_t *ucp, func_t func, uint64_t *args)
98
{
99
(*func)(args[0], args[1], args[2], args[3], args[4], args[5]);
100
if (ucp->uc_link == NULL)
101
exit(0);
102
setcontext((const ucontext_t *)ucp->uc_link);
103
/* should never get here */
104
abort();
105
/* NOTREACHED */
106
}
107
108